dev/pbs-symbol-documentation-and-hover-markdown #13
@ -1,7 +1,7 @@
|
|||||||
{"type":"meta","next_id":{"DSC":39,"AGD":42,"DEC":40,"PLN":103,"LSN":55,"CLSN":1}}
|
{"type":"meta","next_id":{"DSC":39,"AGD":42,"DEC":40,"PLN":103,"LSN":55,"CLSN":1}}
|
||||||
{"type":"discussion","id":"DSC-0038","status":"done","ticket":"studio-packer-rgba8888-asset-pipeline","title":"Studio and Packer RGBA8888 Asset Pipeline Alignment","created_at":"2026-05-23","updated_at":"2026-07-14","tags":["studio","packer","assets","glyph-bank","palette","rgba8888","runtime-alignment"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0053","file":"discussion/lessons/DSC-0038-studio-packer-rgba8888-asset-pipeline/LSN-0053-rgba8888-is-the-canonical-studio-packer-palette-contract.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14"}]}
|
{"type":"discussion","id":"DSC-0038","status":"done","ticket":"studio-packer-rgba8888-asset-pipeline","title":"Studio and Packer RGBA8888 Asset Pipeline Alignment","created_at":"2026-05-23","updated_at":"2026-07-14","tags":["studio","packer","assets","glyph-bank","palette","rgba8888","runtime-alignment"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0053","file":"discussion/lessons/DSC-0038-studio-packer-rgba8888-asset-pipeline/LSN-0053-rgba8888-is-the-canonical-studio-packer-palette-contract.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14"}]}
|
||||||
{"type":"discussion","id":"DSC-0037","status":"done","ticket":"pbs-autocomplete-parameter-names","title":"PBS autocomplete parameter names for stdlib and method calls","created_at":"2026-05-08","updated_at":"2026-05-14","tags":["compiler-pbs","studio","lsp","autocomplete","signature-help","stdlib"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0052","file":"discussion/lessons/DSC-0037-pbs-autocomplete-parameter-names/LSN-0052-canonical-callable-parameter-names-through-pbs-editor-assistance.md","status":"done","created_at":"2026-05-14","updated_at":"2026-05-14"}]}
|
{"type":"discussion","id":"DSC-0037","status":"done","ticket":"pbs-autocomplete-parameter-names","title":"PBS autocomplete parameter names for stdlib and method calls","created_at":"2026-05-08","updated_at":"2026-05-14","tags":["compiler-pbs","studio","lsp","autocomplete","signature-help","stdlib"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0052","file":"discussion/lessons/DSC-0037-pbs-autocomplete-parameter-names/LSN-0052-canonical-callable-parameter-names-through-pbs-editor-assistance.md","status":"done","created_at":"2026-05-14","updated_at":"2026-05-14"}]}
|
||||||
{"type":"discussion","id":"DSC-0036","status":"in_progress","ticket":"pbs-symbol-documentation-and-hover-markdown","title":"Modelo de documentacao de simbolos em PBS e consumo markdown no hover","created_at":"2026-05-08","updated_at":"2026-07-15","tags":["compiler","compiler-pbs","studio","lsp","vscode","editor","hover","documentation","markdown"],"agendas":[{"id":"AGD-0039","file":"AGD-0039-pbs-symbol-documentation-and-hover-markdown.md","status":"accepted","created_at":"2026-05-08","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0039","file":"DEC-0039-pbs-symbol-documentation-with-doc-markdown-text-blocks.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0039"}],"plans":[{"id":"PLN-0092","file":"PLN-0092-specify-pbs-doc-attribute-and-markdown-text-block-syntax.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0093","file":"PLN-0093-implement-pbs-lexer-support-for-documentation-text-blocks.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0094","file":"PLN-0094-extend-pbs-attribute-parser-and-ast-for-doc-markdown-payloads.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0095","file":"PLN-0095-implement-documentation-text-block-normalization.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0096","file":"PLN-0096-validate-doc-attribute-semantics-and-diagnostics.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0097","file":"PLN-0097-attach-doc-metadata-to-pbs-semantic-symbols.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0098","file":"PLN-0098-expose-doc-metadata-through-pbs-editorial-and-lsp-surfaces.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0099","file":"PLN-0099-render-doc-markdown-in-hover-composition.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0100","file":"PLN-0100-author-doc-metadata-for-stdlib-sdk-and-interface-declarations.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0101","file":"PLN-0101-protect-runtime-artifacts-from-doc-metadata-lowering.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0102","file":"PLN-0102-add-end-to-end-doc-documentation-conformance-coverage.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]}],"lessons":[]}
|
{"type":"discussion","id":"DSC-0036","status":"in_progress","ticket":"pbs-symbol-documentation-and-hover-markdown","title":"Modelo de documentacao de simbolos em PBS e consumo markdown no hover","created_at":"2026-05-08","updated_at":"2026-07-15","tags":["compiler","compiler-pbs","studio","lsp","vscode","editor","hover","documentation","markdown"],"agendas":[{"id":"AGD-0039","file":"AGD-0039-pbs-symbol-documentation-and-hover-markdown.md","status":"accepted","created_at":"2026-05-08","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0039","file":"DEC-0039-pbs-symbol-documentation-with-doc-markdown-text-blocks.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0039"}],"plans":[{"id":"PLN-0092","file":"PLN-0092-specify-pbs-doc-attribute-and-markdown-text-block-syntax.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0093","file":"PLN-0093-implement-pbs-lexer-support-for-documentation-text-blocks.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0094","file":"PLN-0094-extend-pbs-attribute-parser-and-ast-for-doc-markdown-payloads.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0095","file":"PLN-0095-implement-documentation-text-block-normalization.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0096","file":"PLN-0096-validate-doc-attribute-semantics-and-diagnostics.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0097","file":"PLN-0097-attach-doc-metadata-to-pbs-semantic-symbols.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0098","file":"PLN-0098-expose-doc-metadata-through-pbs-editorial-and-lsp-surfaces.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0099","file":"PLN-0099-render-doc-markdown-in-hover-composition.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0100","file":"PLN-0100-author-doc-metadata-for-stdlib-sdk-and-interface-declarations.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0101","file":"PLN-0101-protect-runtime-artifacts-from-doc-metadata-lowering.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]},{"id":"PLN-0102","file":"PLN-0102-add-end-to-end-doc-documentation-conformance-coverage.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0039"]}],"lessons":[]}
|
||||||
{"type":"discussion","id":"DSC-0035","status":"done","ticket":"pbs-lsp-editor-assistance-wave-1","title":"Wave 1 de assistencia editorial via LSP para PBS no VS Code","created_at":"2026-05-08","updated_at":"2026-05-08","tags":["studio","lsp","vscode","compiler","compiler-pbs","editor","completion","hover","signature-help"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0051","file":"discussion/lessons/DSC-0035-pbs-lsp-editor-assistance-wave-1/LSN-0051-compiler-backed-editor-assistance-for-pbs.md","status":"done","created_at":"2026-05-08","updated_at":"2026-05-08"}]}
|
{"type":"discussion","id":"DSC-0035","status":"done","ticket":"pbs-lsp-editor-assistance-wave-1","title":"Wave 1 de assistencia editorial via LSP para PBS no VS Code","created_at":"2026-05-08","updated_at":"2026-05-08","tags":["studio","lsp","vscode","compiler","compiler-pbs","editor","completion","hover","signature-help"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0051","file":"discussion/lessons/DSC-0035-pbs-lsp-editor-assistance-wave-1/LSN-0051-compiler-backed-editor-assistance-for-pbs.md","status":"done","created_at":"2026-05-08","updated_at":"2026-05-08"}]}
|
||||||
{"type":"discussion","id":"DSC-0034","status":"done","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-07","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0048","file":"discussion/lessons/DSC-0034-frontend-semantic-host-projection-flexibility/LSN-0048-frontend-owned-semantic-vocabularies-with-declarative-host-projection.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]}
|
{"type":"discussion","id":"DSC-0034","status":"done","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-07","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0048","file":"discussion/lessons/DSC-0034-frontend-semantic-host-projection-flexibility/LSN-0048-frontend-owned-semantic-vocabularies-with-declarative-host-projection.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]}
|
||||||
{"type":"discussion","id":"DSC-0033","status":"done","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-08","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0050","file":"discussion/lessons/DSC-0033-frontend-visual-theme-spec-and-css-retirement/LSN-0050-frontend-owned-visual-themes-with-structured-contract-and-host-adapters.md","status":"done","created_at":"2026-05-08","updated_at":"2026-05-08"}]}
|
{"type":"discussion","id":"DSC-0033","status":"done","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-08","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0050","file":"discussion/lessons/DSC-0033-frontend-visual-theme-spec-and-css-retirement/LSN-0050-frontend-owned-visual-themes-with-structured-contract-and-host-adapters.md","status":"done","created_at":"2026-05-08","updated_at":"2026-05-08"}]}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
id: PLN-0096
|
id: PLN-0096
|
||||||
ticket: pbs-symbol-documentation-and-hover-markdown
|
ticket: pbs-symbol-documentation-and-hover-markdown
|
||||||
title: Validate Doc attribute semantics and diagnostics
|
title: Validate Doc attribute semantics and diagnostics
|
||||||
status: open
|
status: done
|
||||||
created: 2026-07-15
|
created: 2026-07-15
|
||||||
ref_decisions: [DEC-0039]
|
ref_decisions: [DEC-0039]
|
||||||
tags: [compiler, compiler-pbs, studio, lsp, vscode, editor, hover, documentation, markdown]
|
tags: [compiler, compiler-pbs, studio, lsp, vscode, editor, hover, documentation, markdown]
|
||||||
|
|||||||
@ -138,6 +138,7 @@ public final class PbsAst {
|
|||||||
ReturnKind returnKind,
|
ReturnKind returnKind,
|
||||||
TypeRef returnType,
|
TypeRef returnType,
|
||||||
TypeRef resultErrorType,
|
TypeRef resultErrorType,
|
||||||
|
ReadOnlyList<Attribute> attributes,
|
||||||
LifecycleMarker lifecycleMarker,
|
LifecycleMarker lifecycleMarker,
|
||||||
Block body,
|
Block body,
|
||||||
Span span) implements TopDecl {
|
Span span) implements TopDecl {
|
||||||
@ -149,18 +150,21 @@ public final class PbsAst {
|
|||||||
ReadOnlyList<FunctionDecl> methods,
|
ReadOnlyList<FunctionDecl> methods,
|
||||||
ReadOnlyList<CtorDecl> ctors,
|
ReadOnlyList<CtorDecl> ctors,
|
||||||
boolean hasBody,
|
boolean hasBody,
|
||||||
|
ReadOnlyList<Attribute> attributes,
|
||||||
Span span) implements TopDecl {
|
Span span) implements TopDecl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ContractDecl(
|
public record ContractDecl(
|
||||||
String name,
|
String name,
|
||||||
ReadOnlyList<FunctionSignature> signatures,
|
ReadOnlyList<FunctionSignature> signatures,
|
||||||
|
ReadOnlyList<Attribute> attributes,
|
||||||
Span span) implements TopDecl {
|
Span span) implements TopDecl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public record HostDecl(
|
public record HostDecl(
|
||||||
String name,
|
String name,
|
||||||
ReadOnlyList<FunctionSignature> signatures,
|
ReadOnlyList<FunctionSignature> signatures,
|
||||||
|
ReadOnlyList<Attribute> attributes,
|
||||||
Span span) implements TopDecl {
|
Span span) implements TopDecl {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,18 +179,21 @@ public final class PbsAst {
|
|||||||
public record ServiceDecl(
|
public record ServiceDecl(
|
||||||
String name,
|
String name,
|
||||||
ReadOnlyList<FunctionDecl> methods,
|
ReadOnlyList<FunctionDecl> methods,
|
||||||
|
ReadOnlyList<Attribute> attributes,
|
||||||
Span span) implements TopDecl {
|
Span span) implements TopDecl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ErrorDecl(
|
public record ErrorDecl(
|
||||||
String name,
|
String name,
|
||||||
ReadOnlyList<String> cases,
|
ReadOnlyList<String> cases,
|
||||||
|
ReadOnlyList<Attribute> attributes,
|
||||||
Span span) implements TopDecl {
|
Span span) implements TopDecl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public record EnumDecl(
|
public record EnumDecl(
|
||||||
String name,
|
String name,
|
||||||
ReadOnlyList<EnumCase> cases,
|
ReadOnlyList<EnumCase> cases,
|
||||||
|
ReadOnlyList<Attribute> attributes,
|
||||||
Span span) implements TopDecl {
|
Span span) implements TopDecl {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,6 +203,7 @@ public final class PbsAst {
|
|||||||
ReturnKind returnKind,
|
ReturnKind returnKind,
|
||||||
TypeRef returnType,
|
TypeRef returnType,
|
||||||
TypeRef resultErrorType,
|
TypeRef resultErrorType,
|
||||||
|
ReadOnlyList<Attribute> attributes,
|
||||||
Span span) implements TopDecl {
|
Span span) implements TopDecl {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -108,28 +108,28 @@ final class PbsDeclarationParser {
|
|||||||
final PbsToken declareToken,
|
final PbsToken declareToken,
|
||||||
final ReadOnlyList<PbsAst.Attribute> pendingAttributes) {
|
final ReadOnlyList<PbsAst.Attribute> pendingAttributes) {
|
||||||
if (cursor.match(PbsTokenKind.STRUCT)) {
|
if (cursor.match(PbsTokenKind.STRUCT)) {
|
||||||
rejectAttributesBeforeUnsupportedTopDecl(pendingAttributes, "struct declarations");
|
rejectUnsupportedDeclarationAttributes(pendingAttributes, "struct declarations");
|
||||||
return parseStructDeclaration(declareToken);
|
return parseStructDeclaration(declareToken, pendingAttributes);
|
||||||
}
|
}
|
||||||
if (cursor.match(PbsTokenKind.CONTRACT)) {
|
if (cursor.match(PbsTokenKind.CONTRACT)) {
|
||||||
rejectAttributesBeforeUnsupportedTopDecl(pendingAttributes, "contract declarations");
|
rejectUnsupportedDeclarationAttributes(pendingAttributes, "contract declarations");
|
||||||
return parseContractDeclaration(declareToken);
|
return parseContractDeclaration(declareToken, pendingAttributes);
|
||||||
}
|
}
|
||||||
if (cursor.match(PbsTokenKind.SERVICE)) {
|
if (cursor.match(PbsTokenKind.SERVICE)) {
|
||||||
rejectAttributesBeforeUnsupportedTopDecl(pendingAttributes, "service declarations");
|
rejectUnsupportedDeclarationAttributes(pendingAttributes, "service declarations");
|
||||||
return parseServiceDeclaration(declareToken);
|
return parseServiceDeclaration(declareToken, pendingAttributes);
|
||||||
}
|
}
|
||||||
if (cursor.match(PbsTokenKind.ERROR)) {
|
if (cursor.match(PbsTokenKind.ERROR)) {
|
||||||
rejectAttributesBeforeUnsupportedTopDecl(pendingAttributes, "error declarations");
|
rejectUnsupportedDeclarationAttributes(pendingAttributes, "error declarations");
|
||||||
return parseErrorDeclaration(declareToken);
|
return parseErrorDeclaration(declareToken, pendingAttributes);
|
||||||
}
|
}
|
||||||
if (cursor.match(PbsTokenKind.ENUM)) {
|
if (cursor.match(PbsTokenKind.ENUM)) {
|
||||||
rejectAttributesBeforeUnsupportedTopDecl(pendingAttributes, "enum declarations");
|
rejectUnsupportedDeclarationAttributes(pendingAttributes, "enum declarations");
|
||||||
return parseEnumDeclaration(declareToken);
|
return parseEnumDeclaration(declareToken, pendingAttributes);
|
||||||
}
|
}
|
||||||
if (cursor.match(PbsTokenKind.CALLBACK)) {
|
if (cursor.match(PbsTokenKind.CALLBACK)) {
|
||||||
rejectAttributesBeforeUnsupportedTopDecl(pendingAttributes, "callback declarations");
|
rejectUnsupportedDeclarationAttributes(pendingAttributes, "callback declarations");
|
||||||
return parseCallbackDeclaration(declareToken);
|
return parseCallbackDeclaration(declareToken, pendingAttributes);
|
||||||
}
|
}
|
||||||
if (cursor.match(PbsTokenKind.GLOBAL)) {
|
if (cursor.match(PbsTokenKind.GLOBAL)) {
|
||||||
rejectAttributesBeforeUnsupportedTopDecl(pendingAttributes, "global declarations");
|
rejectAttributesBeforeUnsupportedTopDecl(pendingAttributes, "global declarations");
|
||||||
@ -139,14 +139,14 @@ final class PbsDeclarationParser {
|
|||||||
return parseConstDeclaration(declareToken, pendingAttributes);
|
return parseConstDeclaration(declareToken, pendingAttributes);
|
||||||
}
|
}
|
||||||
if (cursor.match(PbsTokenKind.HOST)) {
|
if (cursor.match(PbsTokenKind.HOST)) {
|
||||||
rejectAttributesBeforeUnsupportedTopDecl(pendingAttributes, "host declarations");
|
rejectUnsupportedDeclarationAttributes(pendingAttributes, "host declarations");
|
||||||
if (isNotInterfaceMode()) {
|
if (isNotInterfaceMode()) {
|
||||||
final var end = declarationTerminatorDelegate.consume();
|
final var end = declarationTerminatorDelegate.consume();
|
||||||
report(cursor.previous(), ParseErrors.E_PARSE_RESERVED_DECLARATION,
|
report(cursor.previous(), ParseErrors.E_PARSE_RESERVED_DECLARATION,
|
||||||
"'declare host' is reserved and not supported in ordinary source modules");
|
"'declare host' is reserved and not supported in ordinary source modules");
|
||||||
return new PbsAst.InvalidDecl("reserved declare host", span(declareToken.start(), end));
|
return new PbsAst.InvalidDecl("reserved declare host", span(declareToken.start(), end));
|
||||||
}
|
}
|
||||||
return parseHostDeclaration(declareToken);
|
return parseHostDeclaration(declareToken, pendingAttributes);
|
||||||
}
|
}
|
||||||
if (cursor.match(PbsTokenKind.BUILTIN)) {
|
if (cursor.match(PbsTokenKind.BUILTIN)) {
|
||||||
consume(PbsTokenKind.TYPE, "Expected 'type' in 'declare builtin type' declaration");
|
consume(PbsTokenKind.TYPE, "Expected 'type' in 'declare builtin type' declaration");
|
||||||
@ -211,14 +211,16 @@ final class PbsDeclarationParser {
|
|||||||
span(implementsToken.start(), end));
|
span(implementsToken.start(), end));
|
||||||
}
|
}
|
||||||
|
|
||||||
private PbsAst.HostDecl parseHostDeclaration(final PbsToken declareToken) {
|
private PbsAst.HostDecl parseHostDeclaration(
|
||||||
|
final PbsToken declareToken,
|
||||||
|
final ReadOnlyList<PbsAst.Attribute> attributes) {
|
||||||
final var name = consume(PbsTokenKind.IDENTIFIER, "Expected host declaration name");
|
final var name = consume(PbsTokenKind.IDENTIFIER, "Expected host declaration name");
|
||||||
consume(PbsTokenKind.LEFT_BRACE, "Expected '{' to start host declaration body");
|
consume(PbsTokenKind.LEFT_BRACE, "Expected '{' to start host declaration body");
|
||||||
final var signatures = new ArrayList<PbsAst.FunctionSignature>();
|
final var signatures = new ArrayList<PbsAst.FunctionSignature>();
|
||||||
while (!cursor.check(PbsTokenKind.RIGHT_BRACE) && !cursor.isAtEnd()) {
|
while (!cursor.check(PbsTokenKind.RIGHT_BRACE) && !cursor.isAtEnd()) {
|
||||||
var attributes = ReadOnlyList.<PbsAst.Attribute>empty();
|
var signatureAttributes = ReadOnlyList.<PbsAst.Attribute>empty();
|
||||||
if (cursor.check(PbsTokenKind.LEFT_BRACKET)) {
|
if (cursor.check(PbsTokenKind.LEFT_BRACKET)) {
|
||||||
attributes = attributeParser.parseAttributeList();
|
signatureAttributes = attributeParser.parseAttributeList();
|
||||||
}
|
}
|
||||||
if (!cursor.match(PbsTokenKind.FN)) {
|
if (!cursor.match(PbsTokenKind.FN)) {
|
||||||
report(cursor.peek(), ParseErrors.E_PARSE_INVALID_DECL_SHAPE,
|
report(cursor.peek(), ParseErrors.E_PARSE_INVALID_DECL_SHAPE,
|
||||||
@ -226,12 +228,13 @@ final class PbsDeclarationParser {
|
|||||||
cursor.advance();
|
cursor.advance();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
signatures.add(parseFunctionSignature(cursor.previous(), attributes));
|
signatures.add(parseFunctionSignature(cursor.previous(), signatureAttributes));
|
||||||
}
|
}
|
||||||
final var rightBrace = consume(PbsTokenKind.RIGHT_BRACE, "Expected '}' to end host declaration body");
|
final var rightBrace = consume(PbsTokenKind.RIGHT_BRACE, "Expected '}' to end host declaration body");
|
||||||
return new PbsAst.HostDecl(
|
return new PbsAst.HostDecl(
|
||||||
name.lexeme(),
|
name.lexeme(),
|
||||||
ReadOnlyList.wrap(signatures),
|
ReadOnlyList.wrap(signatures),
|
||||||
|
attributes,
|
||||||
span(declareToken.start(), rightBrace.end()));
|
span(declareToken.start(), rightBrace.end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,7 +311,9 @@ final class PbsDeclarationParser {
|
|||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PbsAst.StructDecl parseStructDeclaration(final PbsToken declareToken) {
|
private PbsAst.StructDecl parseStructDeclaration(
|
||||||
|
final PbsToken declareToken,
|
||||||
|
final ReadOnlyList<PbsAst.Attribute> attributes) {
|
||||||
final var name = consume(PbsTokenKind.IDENTIFIER, "Expected struct name");
|
final var name = consume(PbsTokenKind.IDENTIFIER, "Expected struct name");
|
||||||
consume(PbsTokenKind.LEFT_PAREN, "Expected '(' in struct declaration");
|
consume(PbsTokenKind.LEFT_PAREN, "Expected '(' in struct declaration");
|
||||||
final var fields = parseStructFields();
|
final var fields = parseStructFields();
|
||||||
@ -340,6 +345,7 @@ final class PbsDeclarationParser {
|
|||||||
ReadOnlyList.wrap(methods),
|
ReadOnlyList.wrap(methods),
|
||||||
ReadOnlyList.wrap(ctors),
|
ReadOnlyList.wrap(ctors),
|
||||||
hasBody,
|
hasBody,
|
||||||
|
attributes,
|
||||||
span(declareToken.start(), end));
|
span(declareToken.start(), end));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,17 +417,19 @@ final class PbsDeclarationParser {
|
|||||||
span(ctorToken.start(), body.span().getEnd()));
|
span(ctorToken.start(), body.span().getEnd()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private PbsAst.ContractDecl parseContractDeclaration(final PbsToken declareToken) {
|
private PbsAst.ContractDecl parseContractDeclaration(
|
||||||
|
final PbsToken declareToken,
|
||||||
|
final ReadOnlyList<PbsAst.Attribute> attributes) {
|
||||||
final var name = consume(PbsTokenKind.IDENTIFIER, "Expected contract name");
|
final var name = consume(PbsTokenKind.IDENTIFIER, "Expected contract name");
|
||||||
consume(PbsTokenKind.LEFT_BRACE, "Expected '{' to start contract body");
|
consume(PbsTokenKind.LEFT_BRACE, "Expected '{' to start contract body");
|
||||||
final var signatures = new ArrayList<PbsAst.FunctionSignature>();
|
final var signatures = new ArrayList<PbsAst.FunctionSignature>();
|
||||||
while (!cursor.check(PbsTokenKind.RIGHT_BRACE) && !cursor.isAtEnd()) {
|
while (!cursor.check(PbsTokenKind.RIGHT_BRACE) && !cursor.isAtEnd()) {
|
||||||
var attributes = ReadOnlyList.<PbsAst.Attribute>empty();
|
var signatureAttributes = ReadOnlyList.<PbsAst.Attribute>empty();
|
||||||
if (cursor.check(PbsTokenKind.LEFT_BRACKET)) {
|
if (cursor.check(PbsTokenKind.LEFT_BRACKET)) {
|
||||||
attributes = attributeParser.parseAttributeList();
|
signatureAttributes = attributeParser.parseAttributeList();
|
||||||
if (isOrdinaryMode()) {
|
if (isOrdinaryMode()) {
|
||||||
reportAttributesNotAllowed(attributes, "Attributes are not allowed in ordinary .pbs source modules");
|
reportAttributesNotAllowed(signatureAttributes, "Attributes are not allowed in ordinary .pbs source modules");
|
||||||
attributes = ReadOnlyList.empty();
|
signatureAttributes = ReadOnlyList.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!cursor.match(PbsTokenKind.FN)) {
|
if (!cursor.match(PbsTokenKind.FN)) {
|
||||||
@ -430,13 +438,15 @@ final class PbsDeclarationParser {
|
|||||||
cursor.advance();
|
cursor.advance();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
signatures.add(parseFunctionSignature(cursor.previous(), attributes));
|
signatures.add(parseFunctionSignature(cursor.previous(), signatureAttributes));
|
||||||
}
|
}
|
||||||
final var rightBrace = consume(PbsTokenKind.RIGHT_BRACE, "Expected '}' to end contract body");
|
final var rightBrace = consume(PbsTokenKind.RIGHT_BRACE, "Expected '}' to end contract body");
|
||||||
return new PbsAst.ContractDecl(name.lexeme(), ReadOnlyList.wrap(signatures), span(declareToken.start(), rightBrace.end()));
|
return new PbsAst.ContractDecl(name.lexeme(), ReadOnlyList.wrap(signatures), attributes, span(declareToken.start(), rightBrace.end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private PbsAst.ServiceDecl parseServiceDeclaration(final PbsToken declareToken) {
|
private PbsAst.ServiceDecl parseServiceDeclaration(
|
||||||
|
final PbsToken declareToken,
|
||||||
|
final ReadOnlyList<PbsAst.Attribute> attributes) {
|
||||||
final var name = consume(PbsTokenKind.IDENTIFIER, "Expected service name");
|
final var name = consume(PbsTokenKind.IDENTIFIER, "Expected service name");
|
||||||
consume(PbsTokenKind.LEFT_BRACE, "Expected '{' to start service body");
|
consume(PbsTokenKind.LEFT_BRACE, "Expected '{' to start service body");
|
||||||
final var methods = new ArrayList<PbsAst.FunctionDecl>();
|
final var methods = new ArrayList<PbsAst.FunctionDecl>();
|
||||||
@ -450,10 +460,12 @@ final class PbsDeclarationParser {
|
|||||||
methods.add(parseFunctionLike(cursor.previous(), ReadOnlyList.empty()));
|
methods.add(parseFunctionLike(cursor.previous(), ReadOnlyList.empty()));
|
||||||
}
|
}
|
||||||
final var rightBrace = consume(PbsTokenKind.RIGHT_BRACE, "Expected '}' to end service body");
|
final var rightBrace = consume(PbsTokenKind.RIGHT_BRACE, "Expected '}' to end service body");
|
||||||
return new PbsAst.ServiceDecl(name.lexeme(), ReadOnlyList.wrap(methods), span(declareToken.start(), rightBrace.end()));
|
return new PbsAst.ServiceDecl(name.lexeme(), ReadOnlyList.wrap(methods), attributes, span(declareToken.start(), rightBrace.end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private PbsAst.ErrorDecl parseErrorDeclaration(final PbsToken declareToken) {
|
private PbsAst.ErrorDecl parseErrorDeclaration(
|
||||||
|
final PbsToken declareToken,
|
||||||
|
final ReadOnlyList<PbsAst.Attribute> attributes) {
|
||||||
final var name = consume(PbsTokenKind.IDENTIFIER, "Expected error name");
|
final var name = consume(PbsTokenKind.IDENTIFIER, "Expected error name");
|
||||||
consume(PbsTokenKind.LEFT_BRACE, "Expected '{' to start error body");
|
consume(PbsTokenKind.LEFT_BRACE, "Expected '{' to start error body");
|
||||||
final var cases = new ArrayList<String>();
|
final var cases = new ArrayList<String>();
|
||||||
@ -463,10 +475,12 @@ final class PbsDeclarationParser {
|
|||||||
consume(PbsTokenKind.SEMICOLON, "Expected ';' after error case label");
|
consume(PbsTokenKind.SEMICOLON, "Expected ';' after error case label");
|
||||||
}
|
}
|
||||||
final var rightBrace = consume(PbsTokenKind.RIGHT_BRACE, "Expected '}' to end error body");
|
final var rightBrace = consume(PbsTokenKind.RIGHT_BRACE, "Expected '}' to end error body");
|
||||||
return new PbsAst.ErrorDecl(name.lexeme(), ReadOnlyList.wrap(cases), span(declareToken.start(), rightBrace.end()));
|
return new PbsAst.ErrorDecl(name.lexeme(), ReadOnlyList.wrap(cases), attributes, span(declareToken.start(), rightBrace.end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private PbsAst.EnumDecl parseEnumDeclaration(final PbsToken declareToken) {
|
private PbsAst.EnumDecl parseEnumDeclaration(
|
||||||
|
final PbsToken declareToken,
|
||||||
|
final ReadOnlyList<PbsAst.Attribute> attributes) {
|
||||||
final var name = consume(PbsTokenKind.IDENTIFIER, "Expected enum name");
|
final var name = consume(PbsTokenKind.IDENTIFIER, "Expected enum name");
|
||||||
consume(PbsTokenKind.LEFT_PAREN, "Expected '(' after enum name");
|
consume(PbsTokenKind.LEFT_PAREN, "Expected '(' after enum name");
|
||||||
|
|
||||||
@ -522,7 +536,7 @@ final class PbsDeclarationParser {
|
|||||||
|
|
||||||
final var rightParen = consume(PbsTokenKind.RIGHT_PAREN, "Expected ')' after enum cases");
|
final var rightParen = consume(PbsTokenKind.RIGHT_PAREN, "Expected ')' after enum cases");
|
||||||
final var semicolon = consume(PbsTokenKind.SEMICOLON, "Expected ';' after enum declaration");
|
final var semicolon = consume(PbsTokenKind.SEMICOLON, "Expected ';' after enum declaration");
|
||||||
return new PbsAst.EnumDecl(name.lexeme(), ReadOnlyList.wrap(cases), span(declareToken.start(), Math.max(rightParen.end(), semicolon.end())));
|
return new PbsAst.EnumDecl(name.lexeme(), ReadOnlyList.wrap(cases), attributes, span(declareToken.start(), Math.max(rightParen.end(), semicolon.end())));
|
||||||
}
|
}
|
||||||
|
|
||||||
private PbsAst.FunctionDecl parseFunctionLike(
|
private PbsAst.FunctionDecl parseFunctionLike(
|
||||||
@ -543,6 +557,7 @@ final class PbsDeclarationParser {
|
|||||||
returnSpec.kind(),
|
returnSpec.kind(),
|
||||||
returnSpec.returnType(),
|
returnSpec.returnType(),
|
||||||
returnSpec.resultErrorType(),
|
returnSpec.resultErrorType(),
|
||||||
|
pendingAttributes,
|
||||||
lifecycleMarker,
|
lifecycleMarker,
|
||||||
body,
|
body,
|
||||||
span(fnToken.start(), body.span().getEnd()));
|
span(fnToken.start(), body.span().getEnd()));
|
||||||
@ -585,7 +600,9 @@ final class PbsDeclarationParser {
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PbsAst.CallbackDecl parseCallbackDeclaration(final PbsToken declareToken) {
|
private PbsAst.CallbackDecl parseCallbackDeclaration(
|
||||||
|
final PbsToken declareToken,
|
||||||
|
final ReadOnlyList<PbsAst.Attribute> attributes) {
|
||||||
final var name = consume(PbsTokenKind.IDENTIFIER, "Expected callback name");
|
final var name = consume(PbsTokenKind.IDENTIFIER, "Expected callback name");
|
||||||
consume(PbsTokenKind.LEFT_PAREN, "Expected '(' after callback name");
|
consume(PbsTokenKind.LEFT_PAREN, "Expected '(' after callback name");
|
||||||
final var parameters = typeParser.parseParametersUntilRightParen();
|
final var parameters = typeParser.parseParametersUntilRightParen();
|
||||||
@ -600,6 +617,7 @@ final class PbsDeclarationParser {
|
|||||||
returnSpec.kind(),
|
returnSpec.kind(),
|
||||||
returnSpec.returnType(),
|
returnSpec.returnType(),
|
||||||
returnSpec.resultErrorType(),
|
returnSpec.resultErrorType(),
|
||||||
|
attributes,
|
||||||
span(declareToken.start(), semicolon.end()));
|
span(declareToken.start(), semicolon.end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -651,6 +669,20 @@ final class PbsDeclarationParser {
|
|||||||
reportAttributesNotAllowed(attributes, "Attributes are not allowed before " + targetSurface);
|
reportAttributesNotAllowed(attributes, "Attributes are not allowed before " + targetSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void rejectUnsupportedDeclarationAttributes(
|
||||||
|
final ReadOnlyList<PbsAst.Attribute> attributes,
|
||||||
|
final String targetSurface) {
|
||||||
|
for (final var attribute : attributes) {
|
||||||
|
if ("Doc".equals(attribute.name())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
p.studio.compiler.source.diagnostics.Diagnostics.error(context.diagnostics(),
|
||||||
|
ParseErrors.E_PARSE_ATTRIBUTES_NOT_ALLOWED.name(),
|
||||||
|
"Only [Doc] is allowed before " + targetSurface,
|
||||||
|
attribute.span());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void reportAttributesNotAllowed(
|
private void reportAttributesNotAllowed(
|
||||||
final ReadOnlyList<PbsAst.Attribute> attributes,
|
final ReadOnlyList<PbsAst.Attribute> attributes,
|
||||||
final String message) {
|
final String message) {
|
||||||
@ -684,6 +716,9 @@ final class PbsDeclarationParser {
|
|||||||
PbsAst.LifecycleMarker marker = PbsAst.LifecycleMarker.NONE;
|
PbsAst.LifecycleMarker marker = PbsAst.LifecycleMarker.NONE;
|
||||||
for (final var attribute : attributes) {
|
for (final var attribute : attributes) {
|
||||||
final PbsAst.LifecycleMarker nextMarker;
|
final PbsAst.LifecycleMarker nextMarker;
|
||||||
|
if ("Doc".equals(attribute.name())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if ("Init".equals(attribute.name())) {
|
if ("Init".equals(attribute.name())) {
|
||||||
nextMarker = PbsAst.LifecycleMarker.INIT;
|
nextMarker = PbsAst.LifecycleMarker.INIT;
|
||||||
} else if ("Frame".equals(attribute.name())) {
|
} else if ("Frame".equals(attribute.name())) {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package p.studio.compiler.pbs.semantics;
|
package p.studio.compiler.pbs.semantics;
|
||||||
|
|
||||||
import p.studio.compiler.models.SourceKind;
|
import p.studio.compiler.models.SourceKind;
|
||||||
|
import p.studio.compiler.pbs.PbsDocumentationTextBlockNormalizer;
|
||||||
import p.studio.compiler.pbs.PbsFrontendCompiler;
|
import p.studio.compiler.pbs.PbsFrontendCompiler;
|
||||||
import p.studio.compiler.pbs.ast.PbsAst;
|
import p.studio.compiler.pbs.ast.PbsAst;
|
||||||
import p.studio.compiler.source.Span;
|
import p.studio.compiler.source.Span;
|
||||||
@ -19,6 +20,7 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
private static final String ATTR_INTRINSIC_CALL = "IntrinsicCall";
|
private static final String ATTR_INTRINSIC_CALL = "IntrinsicCall";
|
||||||
private static final String ATTR_INIT_ALLOWED = "InitAllowed";
|
private static final String ATTR_INIT_ALLOWED = "InitAllowed";
|
||||||
private static final String ATTR_ASSET_LOWERING = "AssetLowering";
|
private static final String ATTR_ASSET_LOWERING = "AssetLowering";
|
||||||
|
private static final String ATTR_DOC = "Doc";
|
||||||
|
|
||||||
private static final Set<String> RESERVED_ATTRIBUTES = Set.of(
|
private static final Set<String> RESERVED_ATTRIBUTES = Set.of(
|
||||||
ATTR_HOST,
|
ATTR_HOST,
|
||||||
@ -27,7 +29,8 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
ATTR_BUILTIN_CONST,
|
ATTR_BUILTIN_CONST,
|
||||||
ATTR_INTRINSIC_CALL,
|
ATTR_INTRINSIC_CALL,
|
||||||
ATTR_INIT_ALLOWED,
|
ATTR_INIT_ALLOWED,
|
||||||
ATTR_ASSET_LOWERING);
|
ATTR_ASSET_LOWERING,
|
||||||
|
ATTR_DOC);
|
||||||
|
|
||||||
private final NameTable nameTable;
|
private final NameTable nameTable;
|
||||||
private final PbsConstSemanticsValidator constSemanticsValidator = new PbsConstSemanticsValidator();
|
private final PbsConstSemanticsValidator constSemanticsValidator = new PbsConstSemanticsValidator();
|
||||||
@ -60,6 +63,7 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
|
|
||||||
for (final var topDecl : ast.topDecls()) {
|
for (final var topDecl : ast.topDecls()) {
|
||||||
if (topDecl instanceof PbsAst.FunctionDecl functionDecl) {
|
if (topDecl instanceof PbsAst.FunctionDecl functionDecl) {
|
||||||
|
validateDocAttributes(functionDecl.attributes(), "function declarations", diagnostics);
|
||||||
if (interfaceModule) {
|
if (interfaceModule) {
|
||||||
reportInterfaceNonDeclarativeDecl(
|
reportInterfaceNonDeclarativeDecl(
|
||||||
functionDecl.span(),
|
functionDecl.span(),
|
||||||
@ -82,6 +86,7 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (topDecl instanceof PbsAst.StructDecl structDecl) {
|
if (topDecl instanceof PbsAst.StructDecl structDecl) {
|
||||||
|
validateDocAttributes(structDecl.attributes(), "struct declarations", diagnostics);
|
||||||
binder.registerType(structDecl.name(), structDecl.span(), "struct");
|
binder.registerType(structDecl.name(), structDecl.span(), "struct");
|
||||||
if (interfaceModule && (structDecl.hasBody() || !structDecl.methods().isEmpty() || !structDecl.ctors().isEmpty())) {
|
if (interfaceModule && (structDecl.hasBody() || !structDecl.methods().isEmpty() || !structDecl.ctors().isEmpty())) {
|
||||||
reportInterfaceNonDeclarativeDecl(
|
reportInterfaceNonDeclarativeDecl(
|
||||||
@ -94,6 +99,7 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (topDecl instanceof PbsAst.ServiceDecl serviceDecl) {
|
if (topDecl instanceof PbsAst.ServiceDecl serviceDecl) {
|
||||||
|
validateDocAttributes(serviceDecl.attributes(), "service declarations", diagnostics);
|
||||||
binder.registerType(serviceDecl.name(), serviceDecl.span(), "service");
|
binder.registerType(serviceDecl.name(), serviceDecl.span(), "service");
|
||||||
binder.registerValue(serviceDecl.name(), serviceDecl.span(), "service singleton");
|
binder.registerValue(serviceDecl.name(), serviceDecl.span(), "service singleton");
|
||||||
binder.registerVisibleTopLevelSurface(serviceDecl.name(), serviceDecl.span(), "service");
|
binder.registerVisibleTopLevelSurface(serviceDecl.name(), serviceDecl.span(), "service");
|
||||||
@ -102,10 +108,12 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (topDecl instanceof PbsAst.ContractDecl contractDecl) {
|
if (topDecl instanceof PbsAst.ContractDecl contractDecl) {
|
||||||
|
validateDocAttributes(contractDecl.attributes(), "contract declarations", diagnostics);
|
||||||
binder.registerType(contractDecl.name(), contractDecl.span(), "contract");
|
binder.registerType(contractDecl.name(), contractDecl.span(), "contract");
|
||||||
if (interfaceModule) {
|
if (interfaceModule) {
|
||||||
for (final var signature : contractDecl.signatures()) {
|
for (final var signature : contractDecl.signatures()) {
|
||||||
validateReservedAttributeTarget(signature.attributes(), "contract signature", diagnostics);
|
validateDocAttributes(signature.attributes(), "contract signatures", diagnostics);
|
||||||
|
validateReservedAttributeTargetExceptDoc(signature.attributes(), "contract signature", diagnostics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
validateContractDeclaration(contractDecl, binder, rules);
|
validateContractDeclaration(contractDecl, binder, rules);
|
||||||
@ -113,6 +121,7 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (topDecl instanceof PbsAst.HostDecl hostDecl) {
|
if (topDecl instanceof PbsAst.HostDecl hostDecl) {
|
||||||
|
validateDocAttributes(hostDecl.attributes(), "host declarations", diagnostics);
|
||||||
binder.registerHostOwner(hostDecl.name(), hostDecl.span(), "host owner");
|
binder.registerHostOwner(hostDecl.name(), hostDecl.span(), "host owner");
|
||||||
validateHostDeclaration(hostDecl, binder, rules, interfaceModule, diagnostics);
|
validateHostDeclaration(hostDecl, binder, rules, interfaceModule, diagnostics);
|
||||||
continue;
|
continue;
|
||||||
@ -125,18 +134,21 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (topDecl instanceof PbsAst.ErrorDecl errorDecl) {
|
if (topDecl instanceof PbsAst.ErrorDecl errorDecl) {
|
||||||
|
validateDocAttributes(errorDecl.attributes(), "error declarations", diagnostics);
|
||||||
binder.registerType(errorDecl.name(), errorDecl.span(), "error");
|
binder.registerType(errorDecl.name(), errorDecl.span(), "error");
|
||||||
rules.validateErrorDeclaration(errorDecl);
|
rules.validateErrorDeclaration(errorDecl);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (topDecl instanceof PbsAst.EnumDecl enumDecl) {
|
if (topDecl instanceof PbsAst.EnumDecl enumDecl) {
|
||||||
|
validateDocAttributes(enumDecl.attributes(), "enum declarations", diagnostics);
|
||||||
binder.registerType(enumDecl.name(), enumDecl.span(), "enum");
|
binder.registerType(enumDecl.name(), enumDecl.span(), "enum");
|
||||||
rules.validateEnumDeclaration(enumDecl);
|
rules.validateEnumDeclaration(enumDecl);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (topDecl instanceof PbsAst.CallbackDecl callbackDecl) {
|
if (topDecl instanceof PbsAst.CallbackDecl callbackDecl) {
|
||||||
|
validateDocAttributes(callbackDecl.attributes(), "callback declarations", diagnostics);
|
||||||
binder.registerType(callbackDecl.name(), callbackDecl.span(), "callback");
|
binder.registerType(callbackDecl.name(), callbackDecl.span(), "callback");
|
||||||
rules.validateCallbackDeclaration(callbackDecl);
|
rules.validateCallbackDeclaration(callbackDecl);
|
||||||
continue;
|
continue;
|
||||||
@ -494,12 +506,13 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
final PbsAst.ConstDecl constDecl,
|
final PbsAst.ConstDecl constDecl,
|
||||||
final boolean interfaceModule,
|
final boolean interfaceModule,
|
||||||
final DiagnosticSink diagnostics) {
|
final DiagnosticSink diagnostics) {
|
||||||
|
validateDocAttributes(constDecl.attributes(), "const declarations", diagnostics);
|
||||||
final var builtinConstAttributes = attributesNamed(constDecl.attributes(), ATTR_BUILTIN_CONST);
|
final var builtinConstAttributes = attributesNamed(constDecl.attributes(), ATTR_BUILTIN_CONST);
|
||||||
for (final var attribute : constDecl.attributes()) {
|
for (final var attribute : constDecl.attributes()) {
|
||||||
if (!isReservedAttribute(attribute.name())) {
|
if (!isReservedAttribute(attribute.name())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ATTR_BUILTIN_CONST.equals(attribute.name())) {
|
if (ATTR_BUILTIN_CONST.equals(attribute.name()) || ATTR_DOC.equals(attribute.name())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
reportInvalidReservedAttributeTarget(
|
reportInvalidReservedAttributeTarget(
|
||||||
@ -540,6 +553,7 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
private void validateHostSignatureAttributes(
|
private void validateHostSignatureAttributes(
|
||||||
final PbsAst.FunctionSignature signature,
|
final PbsAst.FunctionSignature signature,
|
||||||
final DiagnosticSink diagnostics) {
|
final DiagnosticSink diagnostics) {
|
||||||
|
validateDocAttributes(signature.attributes(), "host signatures", diagnostics);
|
||||||
final var hostAttributes = attributesNamed(signature.attributes(), ATTR_HOST);
|
final var hostAttributes = attributesNamed(signature.attributes(), ATTR_HOST);
|
||||||
final var initAllowedAttributes = attributesNamed(signature.attributes(), ATTR_INIT_ALLOWED);
|
final var initAllowedAttributes = attributesNamed(signature.attributes(), ATTR_INIT_ALLOWED);
|
||||||
final var assetLoweringAttributes = attributesNamed(signature.attributes(), ATTR_ASSET_LOWERING);
|
final var assetLoweringAttributes = attributesNamed(signature.attributes(), ATTR_ASSET_LOWERING);
|
||||||
@ -550,7 +564,8 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
if (ATTR_HOST.equals(attribute.name())
|
if (ATTR_HOST.equals(attribute.name())
|
||||||
|| ATTR_CAPABILITY.equals(attribute.name())
|
|| ATTR_CAPABILITY.equals(attribute.name())
|
||||||
|| ATTR_INIT_ALLOWED.equals(attribute.name())
|
|| ATTR_INIT_ALLOWED.equals(attribute.name())
|
||||||
|| ATTR_ASSET_LOWERING.equals(attribute.name())) {
|
|| ATTR_ASSET_LOWERING.equals(attribute.name())
|
||||||
|
|| ATTR_DOC.equals(attribute.name())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
reportInvalidReservedAttributeTarget(
|
reportInvalidReservedAttributeTarget(
|
||||||
@ -597,12 +612,13 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
private void validateBuiltinTypeAttribute(
|
private void validateBuiltinTypeAttribute(
|
||||||
final PbsAst.BuiltinTypeDecl builtinTypeDecl,
|
final PbsAst.BuiltinTypeDecl builtinTypeDecl,
|
||||||
final DiagnosticSink diagnostics) {
|
final DiagnosticSink diagnostics) {
|
||||||
|
validateDocAttributes(builtinTypeDecl.attributes(), "builtin type declarations", diagnostics);
|
||||||
final var builtinTypeAttributes = attributesNamed(builtinTypeDecl.attributes(), ATTR_BUILTIN_TYPE);
|
final var builtinTypeAttributes = attributesNamed(builtinTypeDecl.attributes(), ATTR_BUILTIN_TYPE);
|
||||||
for (final var attribute : builtinTypeDecl.attributes()) {
|
for (final var attribute : builtinTypeDecl.attributes()) {
|
||||||
if (!isReservedAttribute(attribute.name())) {
|
if (!isReservedAttribute(attribute.name())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ATTR_BUILTIN_TYPE.equals(attribute.name())) {
|
if (ATTR_BUILTIN_TYPE.equals(attribute.name()) || ATTR_DOC.equals(attribute.name())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
reportInvalidReservedAttributeTarget(
|
reportInvalidReservedAttributeTarget(
|
||||||
@ -645,12 +661,13 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
private void validateIntrinsicCallAttributes(
|
private void validateIntrinsicCallAttributes(
|
||||||
final PbsAst.FunctionSignature signature,
|
final PbsAst.FunctionSignature signature,
|
||||||
final DiagnosticSink diagnostics) {
|
final DiagnosticSink diagnostics) {
|
||||||
|
validateDocAttributes(signature.attributes(), "builtin method signatures", diagnostics);
|
||||||
final var intrinsicAttributes = attributesNamed(signature.attributes(), ATTR_INTRINSIC_CALL);
|
final var intrinsicAttributes = attributesNamed(signature.attributes(), ATTR_INTRINSIC_CALL);
|
||||||
for (final var attribute : signature.attributes()) {
|
for (final var attribute : signature.attributes()) {
|
||||||
if (!isReservedAttribute(attribute.name())) {
|
if (!isReservedAttribute(attribute.name())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ATTR_INTRINSIC_CALL.equals(attribute.name())) {
|
if (ATTR_INTRINSIC_CALL.equals(attribute.name()) || ATTR_DOC.equals(attribute.name())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
reportInvalidReservedAttributeTarget(
|
reportInvalidReservedAttributeTarget(
|
||||||
@ -770,6 +787,47 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateDocAttributes(
|
||||||
|
final ReadOnlyList<PbsAst.Attribute> attributes,
|
||||||
|
final String targetSurface,
|
||||||
|
final DiagnosticSink diagnostics) {
|
||||||
|
final var docAttributes = attributesNamed(attributes, ATTR_DOC);
|
||||||
|
if (docAttributes.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (docAttributes.size() > 1) {
|
||||||
|
for (int i = 1; i < docAttributes.size(); i++) {
|
||||||
|
reportDuplicateReservedAttribute(docAttributes.get(i), ATTR_DOC, diagnostics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
validateDocAttributeShape(docAttributes.getFirst(), targetSurface, diagnostics);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateDocAttributeShape(
|
||||||
|
final PbsAst.Attribute attribute,
|
||||||
|
final String targetSurface,
|
||||||
|
final DiagnosticSink diagnostics) {
|
||||||
|
final var args = validateNamedArguments(attribute, Set.of("markdown"), Set.of(), diagnostics);
|
||||||
|
if (args == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final var value = args.get("markdown");
|
||||||
|
if (!(value instanceof PbsAst.AttributeDocTextBlockValue docValue)) {
|
||||||
|
p.studio.compiler.source.diagnostics.Diagnostics.error(diagnostics,
|
||||||
|
PbsSemanticsErrors.E_SEM_MALFORMED_RESERVED_ATTRIBUTE.name(),
|
||||||
|
"Doc.markdown on %s must be a documentation text block".formatted(targetSurface),
|
||||||
|
attribute.span());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final var normalized = PbsDocumentationTextBlockNormalizer.normalizeLexeme(docValue.value());
|
||||||
|
if (normalized.isBlank()) {
|
||||||
|
p.studio.compiler.source.diagnostics.Diagnostics.error(diagnostics,
|
||||||
|
PbsSemanticsErrors.E_SEM_MALFORMED_RESERVED_ATTRIBUTE.name(),
|
||||||
|
"Doc.markdown on %s must not be empty".formatted(targetSurface),
|
||||||
|
attribute.span());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Map<String, PbsAst.AttributeValue> validateNamedArguments(
|
private Map<String, PbsAst.AttributeValue> validateNamedArguments(
|
||||||
final PbsAst.Attribute attribute,
|
final PbsAst.Attribute attribute,
|
||||||
final Set<String> requiredNames,
|
final Set<String> requiredNames,
|
||||||
@ -911,6 +969,21 @@ public final class PbsDeclarationSemanticsValidator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateReservedAttributeTargetExceptDoc(
|
||||||
|
final ReadOnlyList<PbsAst.Attribute> attributes,
|
||||||
|
final String targetSurface,
|
||||||
|
final DiagnosticSink diagnostics) {
|
||||||
|
for (final var attribute : attributes) {
|
||||||
|
if (!isReservedAttribute(attribute.name()) || ATTR_DOC.equals(attribute.name())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
reportInvalidReservedAttributeTarget(
|
||||||
|
attribute,
|
||||||
|
"Attribute '%s' is not valid on %s".formatted(attribute.name(), targetSurface),
|
||||||
|
diagnostics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void reportInvalidReservedAttributeTarget(
|
private void reportInvalidReservedAttributeTarget(
|
||||||
final PbsAst.Attribute attribute,
|
final PbsAst.Attribute attribute,
|
||||||
final String message,
|
final String message,
|
||||||
|
|||||||
@ -1155,6 +1155,7 @@ public final class PbsEditorialSupportService {
|
|||||||
functionDecl.returnKind(),
|
functionDecl.returnKind(),
|
||||||
functionDecl.returnType(),
|
functionDecl.returnType(),
|
||||||
functionDecl.resultErrorType(),
|
functionDecl.resultErrorType(),
|
||||||
|
functionDecl.attributes(),
|
||||||
functionDecl.lifecycleMarker(),
|
functionDecl.lifecycleMarker(),
|
||||||
functionDecl.body(),
|
functionDecl.body(),
|
||||||
functionDecl.span());
|
functionDecl.span());
|
||||||
@ -1166,6 +1167,7 @@ public final class PbsEditorialSupportService {
|
|||||||
structDecl.methods(),
|
structDecl.methods(),
|
||||||
structDecl.ctors(),
|
structDecl.ctors(),
|
||||||
structDecl.hasBody(),
|
structDecl.hasBody(),
|
||||||
|
structDecl.attributes(),
|
||||||
structDecl.span());
|
structDecl.span());
|
||||||
}
|
}
|
||||||
if (topDecl instanceof PbsAst.BuiltinTypeDecl builtinTypeDecl) {
|
if (topDecl instanceof PbsAst.BuiltinTypeDecl builtinTypeDecl) {
|
||||||
@ -1177,13 +1179,13 @@ public final class PbsEditorialSupportService {
|
|||||||
builtinTypeDecl.span());
|
builtinTypeDecl.span());
|
||||||
}
|
}
|
||||||
if (topDecl instanceof PbsAst.ServiceDecl serviceDecl) {
|
if (topDecl instanceof PbsAst.ServiceDecl serviceDecl) {
|
||||||
return new PbsAst.ServiceDecl(newName, serviceDecl.methods(), serviceDecl.span());
|
return new PbsAst.ServiceDecl(newName, serviceDecl.methods(), serviceDecl.attributes(), serviceDecl.span());
|
||||||
}
|
}
|
||||||
if (topDecl instanceof PbsAst.HostDecl hostDecl) {
|
if (topDecl instanceof PbsAst.HostDecl hostDecl) {
|
||||||
return new PbsAst.HostDecl(newName, hostDecl.signatures(), hostDecl.span());
|
return new PbsAst.HostDecl(newName, hostDecl.signatures(), hostDecl.attributes(), hostDecl.span());
|
||||||
}
|
}
|
||||||
if (topDecl instanceof PbsAst.ContractDecl contractDecl) {
|
if (topDecl instanceof PbsAst.ContractDecl contractDecl) {
|
||||||
return new PbsAst.ContractDecl(newName, contractDecl.signatures(), contractDecl.span());
|
return new PbsAst.ContractDecl(newName, contractDecl.signatures(), contractDecl.attributes(), contractDecl.span());
|
||||||
}
|
}
|
||||||
if (topDecl instanceof PbsAst.CallbackDecl callbackDecl) {
|
if (topDecl instanceof PbsAst.CallbackDecl callbackDecl) {
|
||||||
return new PbsAst.CallbackDecl(
|
return new PbsAst.CallbackDecl(
|
||||||
@ -1192,13 +1194,14 @@ public final class PbsEditorialSupportService {
|
|||||||
callbackDecl.returnKind(),
|
callbackDecl.returnKind(),
|
||||||
callbackDecl.returnType(),
|
callbackDecl.returnType(),
|
||||||
callbackDecl.resultErrorType(),
|
callbackDecl.resultErrorType(),
|
||||||
|
callbackDecl.attributes(),
|
||||||
callbackDecl.span());
|
callbackDecl.span());
|
||||||
}
|
}
|
||||||
if (topDecl instanceof PbsAst.EnumDecl enumDecl) {
|
if (topDecl instanceof PbsAst.EnumDecl enumDecl) {
|
||||||
return new PbsAst.EnumDecl(newName, enumDecl.cases(), enumDecl.span());
|
return new PbsAst.EnumDecl(newName, enumDecl.cases(), enumDecl.attributes(), enumDecl.span());
|
||||||
}
|
}
|
||||||
if (topDecl instanceof PbsAst.ErrorDecl errorDecl) {
|
if (topDecl instanceof PbsAst.ErrorDecl errorDecl) {
|
||||||
return new PbsAst.ErrorDecl(newName, errorDecl.cases(), errorDecl.span());
|
return new PbsAst.ErrorDecl(newName, errorDecl.cases(), errorDecl.attributes(), errorDecl.span());
|
||||||
}
|
}
|
||||||
if (topDecl instanceof PbsAst.GlobalDecl globalDecl) {
|
if (topDecl instanceof PbsAst.GlobalDecl globalDecl) {
|
||||||
return new PbsAst.GlobalDecl(newName, globalDecl.explicitType(), globalDecl.initializer(), globalDecl.span());
|
return new PbsAst.GlobalDecl(newName, globalDecl.explicitType(), globalDecl.initializer(), globalDecl.span());
|
||||||
|
|||||||
@ -372,7 +372,8 @@ final class PbsFlowSemanticSupport {
|
|||||||
}
|
}
|
||||||
if (topDecl instanceof PbsAst.CallbackDecl(
|
if (topDecl instanceof PbsAst.CallbackDecl(
|
||||||
String name, ReadOnlyList<PbsAst.Parameter> parameters, PbsAst.ReturnKind returnKind,
|
String name, ReadOnlyList<PbsAst.Parameter> parameters, PbsAst.ReturnKind returnKind,
|
||||||
PbsAst.TypeRef returnType, PbsAst.TypeRef resultErrorType, Span span
|
PbsAst.TypeRef returnType, PbsAst.TypeRef resultErrorType,
|
||||||
|
ReadOnlyList<PbsAst.Attribute> ignoredAttributes, Span span
|
||||||
)) {
|
)) {
|
||||||
final var symbol = callableFrom(
|
final var symbol = callableFrom(
|
||||||
name,
|
name,
|
||||||
|
|||||||
@ -14,15 +14,27 @@ class PbsInterfaceModuleSemanticsTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldAcceptValidInterfaceModuleReservedMetadataShapes() {
|
void shouldAcceptValidInterfaceModuleReservedMetadataShapes() {
|
||||||
final var source = """
|
final var source = """
|
||||||
|
[Doc(markdown = \"""
|
||||||
|
Packed color value.
|
||||||
|
\""")]
|
||||||
[BuiltinType(name = "color", version = 1)]
|
[BuiltinType(name = "color", version = 1)]
|
||||||
declare builtin type Color(
|
declare builtin type Color(
|
||||||
pub raw: int
|
pub raw: int
|
||||||
) {
|
) {
|
||||||
|
[Doc(markdown = \"""
|
||||||
|
Packs the color.
|
||||||
|
\""")]
|
||||||
[IntrinsicCall(name = "pack", version = 1)]
|
[IntrinsicCall(name = "pack", version = 1)]
|
||||||
fn pack() -> int;
|
fn pack() -> int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Doc(markdown = \"""
|
||||||
|
Graphics host API.
|
||||||
|
\""")]
|
||||||
declare host Gfx {
|
declare host Gfx {
|
||||||
|
[Doc(markdown = \"""
|
||||||
|
Draws one pixel.
|
||||||
|
\""")]
|
||||||
[Host(module = "gfx2d", name = "draw_pixel", version = 1)]
|
[Host(module = "gfx2d", name = "draw_pixel", version = 1)]
|
||||||
[Capability(name = "gfx2d")]
|
[Capability(name = "gfx2d")]
|
||||||
fn draw_pixel(x: int, y: int, c: Color) -> void;
|
fn draw_pixel(x: int, y: int, c: Color) -> void;
|
||||||
@ -43,6 +55,26 @@ class PbsInterfaceModuleSemanticsTest {
|
|||||||
d.getCode().equals(PbsSemanticsErrors.E_SEM_MALFORMED_RESERVED_ATTRIBUTE.name())));
|
d.getCode().equals(PbsSemanticsErrors.E_SEM_MALFORMED_RESERVED_ATTRIBUTE.name())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldRejectDocOnBuiltinFields() {
|
||||||
|
final var source = """
|
||||||
|
[BuiltinType(name = "color", version = 1)]
|
||||||
|
declare builtin type Color(
|
||||||
|
[Doc(markdown = \"""
|
||||||
|
Raw color bits.
|
||||||
|
\""")]
|
||||||
|
pub raw: int
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
final var diagnostics = DiagnosticSink.empty();
|
||||||
|
|
||||||
|
new PbsFrontendCompiler().compileFile(new FileId(0), source, diagnostics, SourceKind.SDK_INTERFACE);
|
||||||
|
|
||||||
|
assertTrue(diagnostics.stream().anyMatch(d ->
|
||||||
|
d.getCode().equals(PbsSemanticsErrors.E_SEM_INVALID_RESERVED_ATTRIBUTE_TARGET.name())));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldRejectInvalidReservedAttributeTargetsAndShapesInInterfaceModule() {
|
void shouldRejectInvalidReservedAttributeTargetsAndShapesInInterfaceModule() {
|
||||||
final var source = """
|
final var source = """
|
||||||
|
|||||||
@ -9,6 +9,69 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
|
|
||||||
class PbsSemanticsDeclarationsTest {
|
class PbsSemanticsDeclarationsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldAcceptDocOnNamedApiDeclarations() {
|
||||||
|
final var source = """
|
||||||
|
[Doc(markdown = \"""
|
||||||
|
Runs the program.
|
||||||
|
\""")]
|
||||||
|
fn run() -> void { return; }
|
||||||
|
|
||||||
|
[Doc(markdown = \"""
|
||||||
|
Holds player state.
|
||||||
|
\""")]
|
||||||
|
declare struct Player(x: int);
|
||||||
|
|
||||||
|
[Doc(markdown = \"""
|
||||||
|
Game services.
|
||||||
|
\""")]
|
||||||
|
declare service Game {
|
||||||
|
fn tick() -> void { return; }
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
final var diagnostics = DiagnosticSink.empty();
|
||||||
|
|
||||||
|
new PbsFrontendCompiler().compileFile(new FileId(0), source, diagnostics);
|
||||||
|
|
||||||
|
assertFalse(diagnostics.stream().anyMatch(d ->
|
||||||
|
d.getCode().equals(PbsSemanticsErrors.E_SEM_MALFORMED_RESERVED_ATTRIBUTE.name())));
|
||||||
|
assertFalse(diagnostics.stream().anyMatch(d ->
|
||||||
|
d.getCode().equals(PbsSemanticsErrors.E_SEM_INVALID_RESERVED_ATTRIBUTE_TARGET.name())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldRejectMalformedDuplicateAndEmptyDocAttributes() {
|
||||||
|
final var source = """
|
||||||
|
[Doc(markdown = \"""
|
||||||
|
First.
|
||||||
|
\""")]
|
||||||
|
[Doc(markdown = \"""
|
||||||
|
Second.
|
||||||
|
\""")]
|
||||||
|
fn duplicated() -> void { return; }
|
||||||
|
|
||||||
|
[Doc(text = \"""
|
||||||
|
Wrong argument.
|
||||||
|
\""")]
|
||||||
|
fn malformed() -> void { return; }
|
||||||
|
|
||||||
|
[Doc(markdown = \"""
|
||||||
|
|
||||||
|
\""")]
|
||||||
|
fn empty() -> void { return; }
|
||||||
|
""";
|
||||||
|
final var diagnostics = DiagnosticSink.empty();
|
||||||
|
|
||||||
|
new PbsFrontendCompiler().compileFile(new FileId(0), source, diagnostics);
|
||||||
|
|
||||||
|
assertTrue(diagnostics.stream().anyMatch(d ->
|
||||||
|
d.getCode().equals(PbsSemanticsErrors.E_SEM_DUPLICATE_RESERVED_ATTRIBUTE.name())));
|
||||||
|
final var malformedCount = diagnostics.stream()
|
||||||
|
.filter(d -> d.getCode().equals(PbsSemanticsErrors.E_SEM_MALFORMED_RESERVED_ATTRIBUTE.name()))
|
||||||
|
.count();
|
||||||
|
assertTrue(malformedCount >= 2);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldAllowFunctionOverloadsWithDifferentShapes() {
|
void shouldAllowFunctionOverloadsWithDifferentShapes() {
|
||||||
final var source = """
|
final var source = """
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user