Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { AstNode, JSDocDocumentationProvider } from 'langium';

/**
* Documentation provider that first tries to use triple-slash comments and falls back to JSDoc comments.
*/
export class ZModelDocumentationProvider extends JSDocDocumentationProvider {
getDocumentation(node: AstNode): string | undefined {
// prefer to user triple-slash comments
if ('comments' in node && Array.isArray(node.comments) && node.comments.length > 0) {
return node.comments.map((c: string) => c.replace(/^[/]*\s*/, '')).join('\n');
}

// fall back to JSDoc comments
return super.getDocumentation(node);
}
}
6 changes: 5 additions & 1 deletion packages/schema/src/language-server/zmodel-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ import { ZModelValidationRegistry, ZModelValidator } from './validator/zmodel-va
import { ZModelCodeActionProvider } from './zmodel-code-action';
import { ZModelCompletionProvider } from './zmodel-completion-provider';
import { ZModelDefinitionProvider } from './zmodel-definition';
import { ZModelDocumentationProvider } from './zmodel-documentation-provider';
import { ZModelFormatter } from './zmodel-formatter';
import { ZModelHighlightProvider } from './zmodel-highlight';
import { ZModelHoverProvider } from './zmodel-hover';
import { ZModelLinker } from './zmodel-linker';
import { ZModelScopeComputation, ZModelScopeProvider } from './zmodel-scope';
import { ZModelSemanticTokenProvider } from './zmodel-semantic';
import ZModelWorkspaceManager from './zmodel-workspace-manager';
import { ZModelWorkspaceManager } from './zmodel-workspace-manager';

/**
* Declaration of custom services - add your own service classes here.
Expand Down Expand Up @@ -77,6 +78,9 @@ export const ZModelModule: Module<ZModelServices, PartialLangiumServices & ZMode
parser: {
GrammarConfig: (services) => createGrammarConfig(services),
},
documentation: {
DocumentationProvider: (services) => new ZModelDocumentationProvider(services),
},
};

// this duplicates createDefaultSharedModule except that a custom WorkspaceManager is used
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { PLUGIN_MODULE_NAME, STD_LIB_MODULE_NAME } from './constants';
/**
* Custom Langium WorkspaceManager implementation which automatically loads stdlib.zmodel
*/
export default class ZModelWorkspaceManager extends DefaultWorkspaceManager {
export class ZModelWorkspaceManager extends DefaultWorkspaceManager {
public pluginModels = new Set<string>();

protected async loadAdditionalDocuments(
Expand Down
29 changes: 15 additions & 14 deletions packages/schema/src/plugins/prisma/schema-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,13 +282,13 @@ export class PrismaSchemaGenerator {
this.generateContainerAttribute(model, attr);
}

decl.attributes
.filter((attr) => attr.decl.ref && !this.isPrismaAttribute(attr))
.forEach((attr) => model.addComment('/// ' + this.zModelGenerator.generate(attr)));

// user defined comments pass-through
decl.comments.forEach((c) => model.addComment(c));

decl.attributes
.filter((attr) => attr.decl.ref && !this.isPrismaAttribute(attr))
.forEach((attr) => model.addComment('/// - _' + this.zModelGenerator.generate(attr) + '_'));

// generate relation fields on base models linking to concrete models
this.generateDelegateRelationForBase(model, decl);

Expand Down Expand Up @@ -765,9 +765,11 @@ export class PrismaSchemaGenerator {

const nonPrismaAttributes = field.attributes.filter((attr) => attr.decl.ref && !this.isPrismaAttribute(attr));

const documentations = nonPrismaAttributes.map((attr) => '/// ' + this.zModelGenerator.generate(attr));
// user defined comments pass-through
const docs: string[] = [...field.comments];
docs.push(...nonPrismaAttributes.map((attr) => '/// - _' + this.zModelGenerator.generate(attr) + '_'));

const result = model.addField(field.name, type, attributes, documentations, addToFront);
const result = model.addField(field.name, type, attributes, docs, addToFront);

if (this.mode === 'logical') {
if (field.attributes.some((attr) => isDefaultWithAuth(attr))) {
Expand All @@ -777,8 +779,6 @@ export class PrismaSchemaGenerator {
}
}

// user defined comments pass-through
field.comments.forEach((c) => result.addComment(c));
return result;
}

Expand Down Expand Up @@ -898,12 +898,12 @@ export class PrismaSchemaGenerator {
this.generateContainerAttribute(_enum, attr);
}

decl.attributes
.filter((attr) => attr.decl.ref && !this.isPrismaAttribute(attr))
.forEach((attr) => _enum.addComment('/// ' + this.zModelGenerator.generate(attr)));

// user defined comments pass-through
decl.comments.forEach((c) => _enum.addComment(c));

decl.attributes
.filter((attr) => attr.decl.ref && !this.isPrismaAttribute(attr))
.forEach((attr) => _enum.addComment('/// - _' + this.zModelGenerator.generate(attr) + '_'));
}

private generateEnumField(_enum: PrismaEnum, field: EnumField) {
Expand All @@ -913,8 +913,9 @@ export class PrismaSchemaGenerator {

const nonPrismaAttributes = field.attributes.filter((attr) => attr.decl.ref && !this.isPrismaAttribute(attr));

const documentations = nonPrismaAttributes.map((attr) => '/// ' + this.zModelGenerator.generate(attr));
_enum.addField(field.name, attributes, documentations.concat(field.comments));
const docs = [...field.comments];
docs.push(...nonPrismaAttributes.map((attr) => '/// - _' + this.zModelGenerator.generate(attr) + '_'));
_enum.addField(field.name, attributes, docs);
}
}

Expand Down
12 changes: 3 additions & 9 deletions packages/schema/src/res/starter.zmodel
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// This is a sample model to get you started.

/**
* A sample data source using local sqlite db.
*/
/// A sample data source using local sqlite db.
datasource db {
provider = 'sqlite'
url = 'file:./dev.db'
Expand All @@ -12,9 +10,7 @@ generator client {
provider = "prisma-client-js"
}

/**
* User model
*/
/// User model
model User {
id String @id @default(cuid())
email String @unique @email @length(6, 32)
Expand All @@ -28,9 +24,7 @@ model User {
@@allow('all', auth() == this)
}

/**
* Post model
*/
/// Post model
model Post {
id String @id @default(cuid())
createdAt DateTime @default(now())
Expand Down
35 changes: 34 additions & 1 deletion packages/schema/tests/generator/prisma-generator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,35 @@ describe('Prisma generator test', () => {
provider = '@core/prisma'
}

/// User roles
enum Role {
/// Admin role
ADMIN
/// Regular role
USER

@@schema("auth")
}

/// My user model
/// defined here
model User {
id String @id
/// the id field
id String @id @allow('read', this == auth())
role Role

@@schema("auth")
@@allow('all', true)
@@deny('update', this != auth())
}

/**
* My post model
* defined here
*/
model Post {
id String @id
@@schema("public")
}
`);

Expand All @@ -70,6 +95,14 @@ describe('Prisma generator test', () => {
'extensions = [pg_trgm, postgis(version: "3.3.2"), uuid_ossp(map: "uuid-ossp", schema: "extensions")]'
);
expect(content).toContain('schemas = ["auth", "public"]');
expect(content).toContain('/// My user model');
expect(content).toContain(`/// - _@@allow('all', true)_`);
expect(content).toContain(`/// the id field`);
expect(content).toContain(`/// - _@allow('read', this == auth())_`);
expect(content).not.toContain('/// My post model');
expect(content).toContain('/// User roles');
expect(content).toContain('/// Admin role');
expect(content).toContain('/// Regular role');
await getDMMF({ datamodel: content });
});

Expand Down
Loading