services/utilities/getMeaningFromLocation(): fix w/ export specifiers

Fixes 44167, but also two other things:

* On an import/export, climb upto the declaration, and use
  `SemanticMeaning.Type` if it's a `type` only import/export.

* Add a `test.rangesInFile()` to fourslash, so it is easy to do multiple
  files in one test without an awkward filter (which was done in one
  more test).
This commit is contained in:
Eli Barzilay
2021-06-16 16:30:20 -04:00
parent eee34d539c
commit fad9122872
4 changed files with 78 additions and 9 deletions

View File

@@ -89,21 +89,30 @@ namespace ts {
export function getMeaningFromLocation(node: Node): SemanticMeaning {
node = getAdjustedReferenceLocation(node);
const parent = node.parent;
if (node.kind === SyntaxKind.SourceFile) {
return SemanticMeaning.Value;
}
else if (node.parent.kind === SyntaxKind.ExportAssignment
|| node.parent.kind === SyntaxKind.ExternalModuleReference
|| node.parent.kind === SyntaxKind.ImportSpecifier
|| node.parent.kind === SyntaxKind.ImportClause
|| isImportEqualsDeclaration(node.parent) && node === node.parent.name) {
else if (isExportAssignment(parent)
|| isExportSpecifier(parent)
|| isExternalModuleReference(parent)
|| isImportSpecifier(parent)
|| isImportClause(parent)
|| isImportEqualsDeclaration(parent) && node === parent.name) {
let decl: Node = parent;
while (decl) {
if (isImportEqualsDeclaration(decl) || isImportClause(decl) || isExportDeclaration(decl)) {
return decl.isTypeOnly ? SemanticMeaning.Type : SemanticMeaning.All;
}
decl = decl.parent;
}
return SemanticMeaning.All;
}
else if (isInRightSideOfInternalImportEqualsDeclaration(node)) {
return getMeaningFromRightHandSideOfImportEquals(node as Identifier);
}
else if (isDeclarationName(node)) {
return getMeaningFromDeclaration(node.parent);
return getMeaningFromDeclaration(parent);
}
else if (isEntityName(node) && findAncestor(node, or(isJSDocNameReference, isJSDocLinkLike, isJSDocMemberName))) {
return SemanticMeaning.All;
@@ -114,11 +123,11 @@ namespace ts {
else if (isNamespaceReference(node)) {
return SemanticMeaning.Namespace;
}
else if (isTypeParameterDeclaration(node.parent)) {
Debug.assert(isJSDocTemplateTag(node.parent.parent)); // Else would be handled by isDeclarationName
else if (isTypeParameterDeclaration(parent)) {
Debug.assert(isJSDocTemplateTag(parent.parent)); // Else would be handled by isDeclarationName
return SemanticMeaning.Type;
}
else if (isLiteralTypeNode(node.parent)) {
else if (isLiteralTypeNode(parent)) {
// This might be T["name"], which is actually referencing a property and not a type. So allow both meanings.
return SemanticMeaning.Type | SemanticMeaning.Value;
}