Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@link and @see resolve C.m as a class property reference #43625

Merged
merged 9 commits into from
Apr 13, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
39 changes: 27 additions & 12 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38854,15 +38854,14 @@ namespace ts {
return node.parent.kind === SyntaxKind.ExpressionWithTypeArguments;
}

function isJSDocEntryNameReference(node: Identifier | PrivateIdentifier | PropertyAccessExpression | QualifiedName): boolean {
function getJSDocEntryNameReference(node: Identifier | PrivateIdentifier | PropertyAccessExpression | QualifiedName): JSDocNameReference | undefined {
while (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent as QualifiedName;
}
while (node.parent.kind === SyntaxKind.PropertyAccessExpression) {
node = node.parent as PropertyAccessExpression;
}

return node.parent.kind === SyntaxKind.JSDocNameReference;
return isJSDocNameReference(node.parent) ? node.parent : undefined;
}

function forEachEnclosingClass<T>(node: Node, callback: (node: Node) => T | undefined): T | undefined {
Expand Down Expand Up @@ -39027,7 +39026,6 @@ namespace ts {
const symbol = getIntrinsicTagSymbol(<JsxOpeningLikeElement>name.parent);
return symbol === unknownSymbol ? undefined : symbol;
}

return resolveEntityName(name, SymbolFlags.Value, /*ignoreErrors*/ false, /*dontResolveAlias*/ true);
}
else if (name.kind === SyntaxKind.PropertyAccessExpression || name.kind === SyntaxKind.QualifiedName) {
Expand All @@ -39049,20 +39047,37 @@ namespace ts {
const meaning = name.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace;
return resolveEntityName(<EntityName>name, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ true);
}
else if (isJSDocEntryNameReference(name)) {
const meaning = SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Value;
return resolveEntityName(<EntityName>name, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ true, getHostSignatureFromJSDoc(name));
}
else if (isJSDocLink(name.parent)) {

const jsdocReference = getJSDocEntryNameReference(name);
if (jsdocReference || isJSDocLink(name.parent)) {
const meaning = SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Value;
return resolveEntityName(<EntityName>name, meaning, /*ignoreErrors*/ true);
}
const symbol = resolveEntityName(name as EntityName, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ false, getHostSignatureFromJSDoc(name));
if (symbol) {
return symbol;
}
else if (isQualifiedName(name) && isIdentifier(name.left)) {
// resolve C.m as a static member first
const links = getNodeLinks(name);
if (links.resolvedSymbol) {
return links.resolvedSymbol;
}
checkQualifiedName(name, CheckMode.Normal);
if (links.resolvedSymbol) {
return links.resolvedSymbol;
}

// then resolve it as an instance member
const s = resolveEntityName(name.left, meaning, /*ignoreErrors*/ false);
if (s) {
const t = getDeclaredTypeOfSymbol(s);
return getPropertyOfType(t, name.right.escapedText);
}
}
}
if (name.parent.kind === SyntaxKind.TypePredicate) {
return resolveEntityName(<Identifier>name, /*meaning*/ SymbolFlags.FunctionScopedVariable);
}

// Do we want to return undefined here?
return undefined;
}

Expand Down
1 change: 0 additions & 1 deletion src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7443,7 +7443,6 @@ namespace ts {
state = JSDocState.SavingComments;
const commentEnd = scanner.getStartPos();
const linkStart = scanner.getTextPos() - 1;
// TODO: redo here
const link = parseJSDocLink(linkStart);
if (link) {
if (!linkEnd) {
Expand Down
5 changes: 5 additions & 0 deletions src/harness/fourslashImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1184,6 +1184,11 @@ namespace FourSlash {
let pos = 0;
for (const { textSpan } of refsByFile.find(refs => refs[0].fileName === fileName) ?? ts.emptyArray) {
const end = textSpan.start + textSpan.length;
if (fileName === marker?.fileName && pos <= marker.position && marker.position < textSpan.start) {
newContent += content.slice(pos, marker.position);
newContent += "/*FIND ALL REFS*/";
pos = marker.position;
}
newContent += content.slice(pos, textSpan.start);
pos = textSpan.start;
// It's easier to read if the /*FIND ALL REFS*/ comment is outside the range markers, which makes
Expand Down
Loading