mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 04:43:37 -05:00
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:
@@ -23,6 +23,10 @@ namespace FourSlashInterface {
|
||||
return this.state.getRanges();
|
||||
}
|
||||
|
||||
public rangesInFile(fileName?: string): FourSlash.Range[] {
|
||||
return this.state.getRangesInFile(fileName);
|
||||
}
|
||||
|
||||
public spans(): ts.TextSpan[] {
|
||||
return this.ranges().map(r => ts.createTextSpan(r.pos, r.end - r.pos));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
55
tests/cases/fourslash/documentHighlightInTypeExport.ts
Normal file
55
tests/cases/fourslash/documentHighlightInTypeExport.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @Filename: /1.ts
|
||||
//// type [|A|] = 1;
|
||||
//// export { [|A|] as [|B|] };
|
||||
|
||||
{
|
||||
const [AType, AExport, asB] = test.rangesInFile("/1.ts");
|
||||
verify.documentHighlightsOf(AType, [AType, AExport, asB]);
|
||||
verify.documentHighlightsOf(AExport, [AType, AExport, asB]);
|
||||
verify.documentHighlightsOf(asB, [asB]);
|
||||
}
|
||||
|
||||
// @Filename: /2.ts
|
||||
//// type [|A|] = 1;
|
||||
//// let [|A|]: [|A|] = 1;
|
||||
//// export { [|A|] as [|B|] };
|
||||
|
||||
{ // a little strange, but the the type/value namespaces work too
|
||||
const [AType, ALet, ADecl, AExport, asB] = test.rangesInFile("/2.ts");
|
||||
verify.documentHighlightsOf(AType, [AType, ADecl, AExport, asB]);
|
||||
verify.documentHighlightsOf(ADecl, [AType, ADecl, AExport, asB]);
|
||||
verify.documentHighlightsOf(ALet, [ALet, AExport, asB]);
|
||||
verify.documentHighlightsOf(AExport, [AType, ALet, ADecl, AExport, asB]);
|
||||
verify.documentHighlightsOf(asB, [asB]);
|
||||
}
|
||||
|
||||
// @Filename: /3.ts
|
||||
//// type [|A|] = 1;
|
||||
//// let [|A|]: [|A|] = 1;
|
||||
//// export type { [|A|] as [|B|] };
|
||||
|
||||
{ // properly handle type only
|
||||
const [AType, ALet, ADecl, AExport, asB] = test.rangesInFile("/3.ts");
|
||||
verify.documentHighlightsOf(AType, [AType, ADecl, AExport, asB]);
|
||||
verify.documentHighlightsOf(ADecl, [AType, ADecl, AExport, asB]);
|
||||
verify.documentHighlightsOf(AExport, [AType, ADecl, AExport, asB]);
|
||||
verify.documentHighlightsOf(ALet, [ALet]);
|
||||
verify.documentHighlightsOf(asB, [asB]);
|
||||
}
|
||||
|
||||
// would be nice if this could work the same for imports too, but getSymbolAtLocation()
|
||||
// of the imported symbol (when aliased) returns undefined
|
||||
|
||||
// // @Filename: /4.ts
|
||||
// //// import type { [|Tee|] as [|T|] } from "whatEveh";
|
||||
// //// let [|T|]: [|T|];
|
||||
//
|
||||
// {
|
||||
// const [TeeImport, asT, TLet, TDecl] = test.rangesInFile("/4.ts");
|
||||
// verify.documentHighlightsOf(TeeImport, [TeeImport, asT, TDecl]);
|
||||
// // verify.documentHighlightsOf(asT, [TeeImport, asT, TDecl]);
|
||||
// // verify.documentHighlightsOf(TDecl, [TeeImport, asT, TDecl]);
|
||||
// // verify.documentHighlightsOf(TLet, [TLet]);
|
||||
// }
|
||||
@@ -187,6 +187,7 @@ declare namespace FourSlashInterface {
|
||||
markerName(m: Marker): string;
|
||||
marker(name?: string): Marker;
|
||||
ranges(): Range[];
|
||||
rangesInFile(fileName?: string): Range[];
|
||||
spans(): Array<{ start: number, length: number }>;
|
||||
rangesByText(): ts.Map<Range[]>;
|
||||
markerByName(s: string): Marker;
|
||||
|
||||
Reference in New Issue
Block a user