Skip to content

Commit b0f5d3b

Browse files
jiashengguoymc9
andauthored
feat: support prisma format indentation (#1256)
Co-authored-by: ymc9 <[email protected]>
1 parent c37bf92 commit b0f5d3b

File tree

6 files changed

+78
-7
lines changed

6 files changed

+78
-7
lines changed

packages/schema/src/cli/actions/format.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ import ora from 'ora';
66
import { CliError } from '../cli-error';
77
import { formatDocument, getDefaultSchemaLocation } from '../cli-util';
88

9-
export async function format(_projectPath: string, options: { schema: string }) {
9+
type Options = {
10+
schema: string;
11+
prismaStyle?: boolean;
12+
};
13+
14+
export async function format(_projectPath: string, options: Options) {
1015
const version = getVersion();
1116
console.log(colors.bold(`⌛️ ZenStack CLI v${version}`));
1217

@@ -18,7 +23,7 @@ export async function format(_projectPath: string, options: { schema: string })
1823

1924
const spinner = ora(`Formatting ${schemaFile}`).start();
2025
try {
21-
const formattedDoc = await formatDocument(schemaFile);
26+
const formattedDoc = await formatDocument(schemaFile, options.prismaStyle);
2227
await writeFile(schemaFile, formattedDoc);
2328
spinner.succeed();
2429
} catch (e) {

packages/schema/src/cli/cli-util.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ export async function checkNewVersion() {
266266
}
267267
}
268268

269-
export async function formatDocument(fileName: string) {
269+
export async function formatDocument(fileName: string, isPrismaStyle = true) {
270270
const services = createZModelServices(NodeFileSystem).ZModel;
271271
const extensions = services.LanguageMetaData.fileExtensions;
272272
if (!extensions.includes(path.extname(fileName))) {
@@ -279,6 +279,8 @@ export async function formatDocument(fileName: string) {
279279

280280
const formatter = services.lsp.Formatter as ZModelFormatter;
281281

282+
formatter.setPrismaStyle(isPrismaStyle);
283+
282284
const identifier = { uri: document.uri.toString() };
283285
const options = formatter.getFormatOptions() ?? {
284286
insertSpaces: true,

packages/schema/src/cli/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ export function createProgram() {
128128
.command('format')
129129
.description('Format a ZenStack schema file.')
130130
.addOption(schemaOption)
131+
.option('--no-prisma-style', 'do not use prisma style')
131132
.action(formatAction);
132133

133134
// make sure config is loaded before actions run

packages/schema/src/language-server/zmodel-formatter.ts

+40-3
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,31 @@ import { FormattingOptions, Range, TextEdit } from 'vscode-languageserver';
55

66
export class ZModelFormatter extends AbstractFormatter {
77
private formatOptions?: FormattingOptions;
8+
private isPrismaStyle = true;
89
protected format(node: AstNode): void {
910
const formatter = this.getNodeFormatter(node);
11+
1012
if (ast.isDataModelField(node)) {
11-
formatter.property('type').prepend(Formatting.oneSpace());
12-
if (node.attributes.length > 0) {
13-
formatter.properties('attributes').prepend(Formatting.oneSpace());
13+
if (this.isPrismaStyle && ast.isDataModel(node.$container)) {
14+
const dataModel = node.$container;
15+
16+
const compareFn = (a: number, b: number) => b - a;
17+
const maxNameLength = dataModel.fields.map((x) => x.name.length).sort(compareFn)[0];
18+
const maxTypeLength = dataModel.fields.map(this.getFieldTypeLength).sort(compareFn)[0];
19+
20+
formatter.property('type').prepend(Formatting.spaces(maxNameLength - node.name.length + 1));
21+
if (node.attributes.length > 0) {
22+
formatter
23+
.node(node.attributes[0])
24+
.prepend(Formatting.spaces(maxTypeLength - this.getFieldTypeLength(node) + 1));
25+
26+
formatter.nodes(...node.attributes.slice(1)).prepend(Formatting.oneSpace());
27+
}
28+
} else {
29+
formatter.property('type').prepend(Formatting.oneSpace());
30+
if (node.attributes.length > 0) {
31+
formatter.properties('attributes').prepend(Formatting.oneSpace());
32+
}
1433
}
1534
} else if (ast.isDataModelFieldAttribute(node)) {
1635
formatter.keyword('(').surround(Formatting.noSpace());
@@ -52,4 +71,22 @@ export class ZModelFormatter extends AbstractFormatter {
5271
public getIndent() {
5372
return 1;
5473
}
74+
75+
public setPrismaStyle(isPrismaStyle: boolean) {
76+
this.isPrismaStyle = isPrismaStyle;
77+
}
78+
79+
private getFieldTypeLength(field: ast.DataModelField) {
80+
let length = (field.type.type || field.type.reference?.$refText)!.length;
81+
82+
if (field.type.optional) {
83+
length += 1;
84+
}
85+
86+
if (field.type.array) {
87+
length += 2;
88+
}
89+
90+
return length;
91+
}
5592
}

packages/schema/tests/schema/formatter.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ plugin swrHooks {
2525
output = 'lib/hooks'
2626
}
2727
model User {
28-
id String @id
28+
id String @id
2929
name String?
3030
}
3131
enum Role {

tests/integration/tests/cli/format.test.ts

+26
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,32 @@ generator client {
3535
model Post {
3636
id Int @id() @default(autoincrement())
3737
users User[]
38+
}`;
39+
// set up schema
40+
fs.writeFileSync('schema.zmodel', model, 'utf-8');
41+
const program = createProgram();
42+
await program.parseAsync(['format', '--no-prisma-style'], { from: 'user' });
43+
44+
expect(fs.readFileSync('schema.zmodel', 'utf-8')).toEqual(formattedModel);
45+
});
46+
47+
it('prisma format', async () => {
48+
const model = `
49+
datasource db {provider="sqlite" url="file:./dev.db"}
50+
generator client {provider = "prisma-client-js"}
51+
model Post {id Int @id() @default(autoincrement())users User[]}`;
52+
53+
const formattedModel = `
54+
datasource db {
55+
provider="sqlite"
56+
url="file:./dev.db"
57+
}
58+
generator client {
59+
provider = "prisma-client-js"
60+
}
61+
model Post {
62+
id Int @id() @default(autoincrement())
63+
users User[]
3864
}`;
3965
// set up schema
4066
fs.writeFileSync('schema.zmodel', model, 'utf-8');

0 commit comments

Comments
 (0)