Skip to content

Commit

Permalink
Fix directive parsing on namespaces (#3180)
Browse files Browse the repository at this point in the history
Fixes #3165.

Ensures that decorators and directives are attached the leaf node on
Namespace chains.
  • Loading branch information
tjprescott committed Apr 16, 2024
1 parent 083ba8d commit fec9990
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 5 deletions.
8 changes: 8 additions & 0 deletions .chronus/changes/fixDirectiveParsing-2024-3-16-17-9-37.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
changeKind: fix
packages:
- "@typespec/compiler"
---

Fix issue where directives were not parsed to the leaf node in multi-segment Namespace segments.
12 changes: 7 additions & 5 deletions packages/compiler/src/core/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ function createParser(code: string | SourceFile, options: ParseOptions = {}): Pa
item = parseScalarStatement(pos, decorators);
break;
case Token.NamespaceKeyword:
item = parseNamespaceStatement(pos, decorators, docs);
item = parseNamespaceStatement(pos, decorators, docs, directives);
break;
case Token.InterfaceKeyword:
item = parseInterfaceStatement(pos, decorators);
Expand Down Expand Up @@ -461,8 +461,8 @@ function createParser(code: string | SourceFile, options: ParseOptions = {}): Pa
break;
}

mutate(item).directives = directives;
if (tok !== Token.NamespaceKeyword) {
mutate(item).directives = directives;
mutate(item).docs = docs;
}

Expand Down Expand Up @@ -515,7 +515,7 @@ function createParser(code: string | SourceFile, options: ParseOptions = {}): Pa
item = parseScalarStatement(pos, decorators);
break;
case Token.NamespaceKeyword:
const ns = parseNamespaceStatement(pos, decorators, docs);
const ns = parseNamespaceStatement(pos, decorators, docs, directives);

if (!Array.isArray(ns.statements)) {
error({ code: "blockless-namespace-first", messageId: "topLevel", target: ns });
Expand Down Expand Up @@ -595,7 +595,8 @@ function createParser(code: string | SourceFile, options: ParseOptions = {}): Pa
function parseNamespaceStatement(
pos: number,
decorators: DecoratorExpressionNode[],
docs: DocNode[]
docs: DocNode[],
directives: DirectiveExpressionNode[]
): NamespaceStatementNode {
parseExpected(Token.NamespaceKeyword);
let currentName = parseIdentifierOrMemberExpression();
Expand All @@ -621,14 +622,15 @@ function createParser(code: string | SourceFile, options: ParseOptions = {}): Pa
id: nsSegments[0],
locals: undefined!,
statements,

directives: directives,
...finishNode(pos),
};

for (let i = 1; i < nsSegments.length; i++) {
outerNs = {
kind: SyntaxKind.NamespaceStatement,
decorators: [],
directives: [],
id: nsSegments[i],
statements: outerNs,
locals: undefined!,
Expand Down
20 changes: 20 additions & 0 deletions packages/compiler/test/parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,26 @@ describe("compiler: parser", () => {
{ strict: true }
);
});

describe("ensure directives and decorators are applied to leaf node", () => {
parseEach([
[
`@doc("foo")\n#suppress "foo"\nnamespace Foo.Bar {}`,
(node) => {
const fooNs = node.statements[0];
strictEqual(fooNs.kind, SyntaxKind.NamespaceStatement);
const barNs = (fooNs as any).statements;
strictEqual(barNs.kind, SyntaxKind.NamespaceStatement);
strictEqual(fooNs.id.sv, "Foo");
strictEqual(barNs.id.sv, "Bar");
strictEqual(fooNs.directives?.length, 0);
strictEqual(fooNs.decorators.length, 0);
strictEqual(barNs.directives?.length, 1);
strictEqual(barNs.decorators.length, 1);
},
],
]);
});
});

describe("augment decorator statements", () => {
Expand Down

0 comments on commit fec9990

Please sign in to comment.