Skip to content

Commit

Permalink
Fix: Do not crash when trying to access member of aliased expression (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheeguerin authored Apr 23, 2024
1 parent b7e45f0 commit eb11851
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 5 deletions.
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: Do not crash when trying to access member of aliased expressions
32 changes: 27 additions & 5 deletions packages/compiler/src/core/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2402,10 +2402,24 @@ export function createChecker(program: Program): Checker {

// when resolving a type reference based on an alias, unwrap the alias.
if (base.flags & SymbolFlags.Alias) {
base = getAliasedSymbol(base, mapper, options);
if (!base) {
const aliasedSym = getAliasedSymbol(base, mapper, options);
if (!aliasedSym) {
reportCheckerDiagnostic(
createDiagnostic({
code: "invalid-ref",
messageId: "node",
format: {
id: node.id.sv,
nodeName: base.declarations[0]
? SyntaxKind[base.declarations[0].kind]
: "Unknown node",
},
target: node,
})
);
return undefined;
}
base = aliasedSym;
}

if (node.selector === ".") {
Expand Down Expand Up @@ -2561,11 +2575,19 @@ export function createChecker(program: Program): Checker {
while (current.flags & SymbolFlags.Alias) {
const node = current.declarations[0];
const targetNode = node.kind === SyntaxKind.AliasStatement ? node.value : node;
const sym = resolveTypeReferenceSymInternal(targetNode as any, mapper, options);
if (sym === undefined) {
if (
targetNode.kind === SyntaxKind.TypeReference ||
targetNode.kind === SyntaxKind.MemberExpression ||
targetNode.kind === SyntaxKind.Identifier
) {
const sym = resolveTypeReferenceSymInternal(targetNode, mapper, options);
if (sym === undefined) {
return undefined;
}
current = sym;
} else {
return undefined;
}
current = sym;
}
const sym = current;
const node = aliasSymbol.declarations[0];
Expand Down
34 changes: 34 additions & 0 deletions packages/compiler/test/checker/alias.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,4 +258,38 @@ describe("compiler: aliases", () => {
const diagnostics = await testHost.diagnose("main.tsp");
expectDiagnosticEmpty(diagnostics);
});

// REGRESSION TEST: https://github.com/microsoft/typespec/issues/3125
it("trying to access member of aliased union expression shouldn't crash", async () => {
testHost.addTypeSpecFile(
"main.tsp",
`
alias A = {foo: string} | {bar: string};
alias Aliased = A.prop;
`
);
const diagnostics = await testHost.diagnose("main.tsp");
expectDiagnostics(diagnostics, {
code: "invalid-ref",
message: `Cannot resolve 'prop' in node AliasStatement since it has no members. Did you mean to use "::" instead of "."?`,
});
});
it("trying to access member of aliased model expression shouldn't crash", async () => {
testHost.addTypeSpecFile(
"main.tsp",
`
alias A = {foo: string};
alias Aliased = A.prop;
`
);
const diagnostics = await testHost.diagnose("main.tsp");
expectDiagnostics(diagnostics, {
code: "invalid-ref",
message: `Cannot resolve 'prop' in node AliasStatement since it has no members. Did you mean to use "::" instead of "."?`,
});
});
});

0 comments on commit eb11851

Please sign in to comment.