Merge pull request #15737 from Microsoft/findAllRefs_module

Support find-all-references for a module specifier
This commit is contained in:
Andy
2017-05-19 08:11:56 -07:00
committed by GitHub
45 changed files with 313 additions and 157 deletions

View File

@@ -529,7 +529,8 @@ namespace ts {
getFileProcessingDiagnostics: () => fileProcessingDiagnostics,
getResolvedTypeReferenceDirectives: () => resolvedTypeReferenceDirectives,
isSourceFileFromExternalLibrary,
dropDiagnosticsProducingTypeChecker
dropDiagnosticsProducingTypeChecker,
getSourceFileFromReference,
};
verifyCompilerOptions();
@@ -1442,48 +1443,60 @@ namespace ts {
}
}
function processSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number) {
let diagnosticArgument: string[];
let diagnostic: DiagnosticMessage;
/** This should have similar behavior to 'processSourceFile' without diagnostics or mutation. */
function getSourceFileFromReference(referencingFile: SourceFile, ref: FileReference): SourceFile | undefined {
return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), fileName => filesByName.get(toPath(fileName, currentDirectory, getCanonicalFileName)));
}
function getSourceFileFromReferenceWorker(
fileName: string,
getSourceFile: (fileName: string) => SourceFile | undefined,
fail?: (diagnostic: DiagnosticMessage, ...argument: string[]) => void,
refFile?: SourceFile): SourceFile | undefined {
if (hasExtension(fileName)) {
if (!options.allowNonTsExtensions && !forEach(supportedExtensions, extension => fileExtensionIs(host.getCanonicalFileName(fileName), extension))) {
diagnostic = Diagnostics.File_0_has_unsupported_extension_The_only_supported_extensions_are_1;
diagnosticArgument = [fileName, "'" + supportedExtensions.join("', '") + "'"];
if (fail) fail(Diagnostics.File_0_has_unsupported_extension_The_only_supported_extensions_are_1, fileName, "'" + supportedExtensions.join("', '") + "'");
return undefined;
}
else if (!findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd)) {
diagnostic = Diagnostics.File_0_not_found;
diagnosticArgument = [fileName];
}
else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) {
diagnostic = Diagnostics.A_file_cannot_have_a_reference_to_itself;
diagnosticArgument = [fileName];
}
}
else {
const nonTsFile: SourceFile = options.allowNonTsExtensions && findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd);
if (!nonTsFile) {
if (options.allowNonTsExtensions) {
diagnostic = Diagnostics.File_0_not_found;
diagnosticArgument = [fileName];
}
else if (!forEach(supportedExtensions, extension => findSourceFile(fileName + extension, toPath(fileName + extension, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd))) {
diagnostic = Diagnostics.File_0_not_found;
fileName += ".ts";
diagnosticArgument = [fileName];
}
}
}
if (diagnostic) {
if (refFile !== undefined && refEnd !== undefined && refPos !== undefined) {
fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos, diagnostic, ...diagnosticArgument));
const sourceFile = getSourceFile(fileName);
if (fail) {
if (!sourceFile) {
fail(Diagnostics.File_0_not_found, fileName);
}
else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) {
fail(Diagnostics.A_file_cannot_have_a_reference_to_itself, fileName);
}
}
else {
fileProcessingDiagnostics.add(createCompilerDiagnostic(diagnostic, ...diagnosticArgument));
return sourceFile;
} else {
const sourceFileNoExtension = options.allowNonTsExtensions && getSourceFile(fileName);
if (sourceFileNoExtension) return sourceFileNoExtension;
if (fail && options.allowNonTsExtensions) {
fail(Diagnostics.File_0_not_found, fileName);
return undefined;
}
const sourceFileWithAddedExtension = forEach(supportedExtensions, extension => getSourceFile(fileName + extension));
if (fail && !sourceFileWithAddedExtension) fail(Diagnostics.File_0_not_found, fileName + ".ts");
return sourceFileWithAddedExtension;
}
}
/** This has side effects through `findSourceFile`. */
function processSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): void {
getSourceFileFromReferenceWorker(fileName,
fileName => findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd),
(diagnostic, ...args) => {
fileProcessingDiagnostics.add(refFile !== undefined && refEnd !== undefined && refPos !== undefined
? createFileDiagnostic(refFile, refPos, refEnd - refPos, diagnostic, ...args)
: createCompilerDiagnostic(diagnostic, ...args));
},
refFile);
}
function reportFileNamesDifferOnlyInCasingError(fileName: string, existingFileName: string, refFile: SourceFile, refPos: number, refEnd: number): void {
if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) {
fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos,

View File

@@ -2425,6 +2425,8 @@ namespace ts {
/* @internal */ isSourceFileFromExternalLibrary(file: SourceFile): boolean;
// For testing purposes only.
/* @internal */ structureIsReused?: StructureIsReused;
/* @internal */ getSourceFileFromReference(referencingFile: SourceFile, ref: FileReference): SourceFile | undefined;
}
/* @internal */

View File

@@ -1918,21 +1918,19 @@ namespace ts {
const isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)('|")(.+?)\2\s*\/>/gim;
if (simpleReferenceRegEx.test(comment)) {
if (isNoDefaultLibRegEx.test(comment)) {
return {
isNoDefaultLib: true
};
return { isNoDefaultLib: true };
}
else {
const refMatchResult = fullTripleSlashReferencePathRegEx.exec(comment);
const refLibResult = !refMatchResult && fullTripleSlashReferenceTypeReferenceDirectiveRegEx.exec(comment);
if (refMatchResult || refLibResult) {
const start = commentRange.pos;
const end = commentRange.end;
const match = refMatchResult || refLibResult;
if (match) {
const pos = commentRange.pos + match[1].length + match[2].length;
return {
fileReference: {
pos: start,
end: end,
fileName: (refMatchResult || refLibResult)[3]
pos,
end: pos + match[3].length,
fileName: match[3]
},
isNoDefaultLib: false,
isTypeReferenceDirective: !!refLibResult

View File

@@ -995,8 +995,7 @@ namespace FourSlash {
public verifyReferenceGroups(startRanges: Range | Range[], parts: Array<{ definition: string, ranges: Range[] }>): void {
interface ReferenceJson { definition: string; ranges: ts.ReferenceEntry[]; }
type ReferencesJson = ReferenceJson[];
const fullExpected = parts.map<ReferenceJson>(({ definition, ranges }) => ({ definition, ranges: ranges.map(rangeToReferenceEntry) }));
const fullExpected = ts.map(parts, ({ definition, ranges }) => ({ definition, ranges: ranges.map(rangeToReferenceEntry) }));
for (const startRange of toArray(startRanges)) {
this.goToRangeStart(startRange);
@@ -1004,7 +1003,7 @@ namespace FourSlash {
definition: definition.displayParts.map(d => d.text).join(""),
ranges: references
}));
this.assertObjectsEqual<ReferencesJson>(fullActual, fullExpected);
this.assertObjectsEqual(fullActual, fullExpected);
}
function rangeToReferenceEntry(r: Range): ts.ReferenceEntry {
@@ -1062,6 +1061,14 @@ namespace FourSlash {
}
}
};
if (fullActual === undefined || fullExpected === undefined) {
if (fullActual === fullExpected) {
return;
}
console.log("Expected:", stringify(fullExpected));
console.log("Actual: ", stringify(fullActual));
this.raiseError(msgPrefix);
}
recur(fullActual, fullExpected, "");
}

View File

@@ -37,8 +37,8 @@ describe("PreProcessFile:", function () {
/*readImportFile*/ true,
/*detectJavaScriptImports*/ false,
{
referencedFiles: [{ fileName: "refFile1.ts", pos: 0, end: 37 }, { fileName: "refFile2.ts", pos: 38, end: 73 },
{ fileName: "refFile3.ts", pos: 74, end: 109 }, { fileName: "..\\refFile4d.ts", pos: 110, end: 150 }],
referencedFiles: [{ fileName: "refFile1.ts", pos: 22, end: 33 }, { fileName: "refFile2.ts", pos: 59, end: 70 },
{ fileName: "refFile3.ts", pos: 94, end: 105 }, { fileName: "..\\refFile4d.ts", pos: 131, end: 146 }],
importedFiles: <ts.FileReference[]>[],
typeReferenceDirectives: [],
ambientExternalModules: undefined,
@@ -104,7 +104,7 @@ describe("PreProcessFile:", function () {
/*readImportFile*/ true,
/*detectJavaScriptImports*/ false,
{
referencedFiles: [{ fileName: "refFile1.ts", pos: 0, end: 35 }, { fileName: "refFile2.ts", pos: 36, end: 71 }],
referencedFiles: [{ fileName: "refFile1.ts", pos: 20, end: 31 }, { fileName: "refFile2.ts", pos: 57, end: 68 }],
typeReferenceDirectives: [],
importedFiles: [{ fileName: "r1.ts", pos: 92, end: 97 }, { fileName: "r2.ts", pos: 121, end: 126 }],
ambientExternalModules: undefined,
@@ -117,7 +117,7 @@ describe("PreProcessFile:", function () {
/*readImportFile*/ true,
/*detectJavaScriptImports*/ false,
{
referencedFiles: [{ fileName: "refFile1.ts", pos: 0, end: 35 }],
referencedFiles: [{ fileName: "refFile1.ts", pos: 20, end: 31 }],
typeReferenceDirectives: [],
importedFiles: [{ fileName: "r1.ts", pos: 91, end: 96 }, { fileName: "r3.ts", pos: 148, end: 153 }],
ambientExternalModules: undefined,
@@ -442,12 +442,12 @@ describe("PreProcessFile:", function () {
/*detectJavaScriptImports*/ false,
{
referencedFiles: [
{ "pos": 13, "end": 38, "fileName": "a" },
{ "pos": 91, "end": 117, "fileName": "a2" }
{ "pos": 34, "end": 35, "fileName": "a" },
{ "pos": 112, "end": 114, "fileName": "a2" }
],
typeReferenceDirectives: [
{ "pos": 51, "end": 78, "fileName": "a1" },
{ "pos": 130, "end": 157, "fileName": "a3" }
{ "pos": 73, "end": 75, "fileName": "a1" },
{ "pos": 152, "end": 154, "fileName": "a3" }
],
importedFiles: [],
ambientExternalModules: undefined,

View File

@@ -1,8 +1,8 @@
/* @internal */
namespace ts.DocumentHighlights {
export function getDocumentHighlights(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] {
export function getDocumentHighlights(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] {
const node = getTouchingWord(sourceFile, position);
return node && (getSemanticDocumentHighlights(node, typeChecker, cancellationToken, sourceFilesToSearch) || getSyntacticDocumentHighlights(node, sourceFile));
return node && (getSemanticDocumentHighlights(node, program, cancellationToken, sourceFilesToSearch) || getSyntacticDocumentHighlights(node, sourceFile));
}
function getHighlightSpanForNode(node: Node, sourceFile: SourceFile): HighlightSpan {
@@ -16,8 +16,8 @@ namespace ts.DocumentHighlights {
};
}
function getSemanticDocumentHighlights(node: Node, typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] {
const referenceEntries = FindAllReferences.getReferenceEntriesForNode(node, sourceFilesToSearch, typeChecker, cancellationToken);
function getSemanticDocumentHighlights(node: Node, program: Program, cancellationToken: CancellationToken, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] {
const referenceEntries = FindAllReferences.getReferenceEntriesForNode(node, program, sourceFilesToSearch, cancellationToken);
return referenceEntries && convertReferencedSymbols(referenceEntries);
}

View File

@@ -41,14 +41,15 @@ namespace ts.FindAllReferences {
readonly implementations?: boolean;
}
export function findReferencedSymbols(checker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number): ReferencedSymbol[] | undefined {
const referencedSymbols = findAllReferencedSymbols(checker, cancellationToken, sourceFiles, sourceFile, position);
export function findReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number): ReferencedSymbol[] | undefined {
const referencedSymbols = findAllReferencedSymbols(program, cancellationToken, sourceFiles, sourceFile, position);
if (!referencedSymbols || !referencedSymbols.length) {
return undefined;
}
const out: ReferencedSymbol[] = [];
const checker = program.getTypeChecker();
for (const { definition, references } of referencedSymbols) {
// Only include referenced symbols that have a valid definition.
if (definition) {
@@ -59,44 +60,46 @@ namespace ts.FindAllReferences {
return out;
}
export function getImplementationsAtPosition(checker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number): ImplementationLocation[] {
export function getImplementationsAtPosition(program: Program, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number): ImplementationLocation[] {
const node = getTouchingPropertyName(sourceFile, position);
const referenceEntries = getImplementationReferenceEntries(checker, cancellationToken, sourceFiles, node);
const referenceEntries = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node);
const checker = program.getTypeChecker();
return map(referenceEntries, entry => toImplementationLocation(entry, checker));
}
function getImplementationReferenceEntries(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], node: Node): Entry[] | undefined {
function getImplementationReferenceEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: SourceFile[], node: Node): Entry[] | undefined {
const checker = program.getTypeChecker();
// If invoked directly on a shorthand property assignment, then return
// the declaration of the symbol being assigned (not the symbol being assigned to).
if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) {
const result: NodeEntry[] = [];
Core.getReferenceEntriesForShorthandPropertyAssignment(node, typeChecker, node => result.push(nodeEntry(node)));
Core.getReferenceEntriesForShorthandPropertyAssignment(node, checker, node => result.push(nodeEntry(node)));
return result;
}
else if (node.kind === SyntaxKind.SuperKeyword || isSuperProperty(node.parent)) {
// References to and accesses on the super keyword only have one possible implementation, so no
// need to "Find all References"
const symbol = typeChecker.getSymbolAtLocation(node);
const symbol = checker.getSymbolAtLocation(node);
return symbol.valueDeclaration && [nodeEntry(symbol.valueDeclaration)];
}
else {
// Perform "Find all References" and retrieve only those that are implementations
return getReferenceEntriesForNode(node, sourceFiles, typeChecker, cancellationToken, { implementations: true });
return getReferenceEntriesForNode(node, program, sourceFiles, cancellationToken, { implementations: true });
}
}
export function findReferencedEntries(checker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, options?: Options): ReferenceEntry[] | undefined {
const x = flattenEntries(findAllReferencedSymbols(checker, cancellationToken, sourceFiles, sourceFile, position, options));
export function findReferencedEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, options?: Options): ReferenceEntry[] | undefined {
const x = flattenEntries(findAllReferencedSymbols(program, cancellationToken, sourceFiles, sourceFile, position, options));
return map(x, toReferenceEntry);
}
export function getReferenceEntriesForNode(node: Node, sourceFiles: SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken, options: Options = {}): Entry[] | undefined {
return flattenEntries(Core.getReferencedSymbolsForNode(node, sourceFiles, checker, cancellationToken, options));
export function getReferenceEntriesForNode(node: Node, program: Program, sourceFiles: SourceFile[], cancellationToken: CancellationToken, options: Options = {}): Entry[] | undefined {
return flattenEntries(Core.getReferencedSymbolsForNode(node, program, sourceFiles, cancellationToken, options));
}
function findAllReferencedSymbols(checker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, options?: Options): SymbolAndEntries[] | undefined {
function findAllReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, options?: Options): SymbolAndEntries[] | undefined {
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
return Core.getReferencedSymbolsForNode(node, sourceFiles, checker, cancellationToken, options);
return Core.getReferencedSymbolsForNode(node, program, sourceFiles, cancellationToken, options);
}
function flattenEntries(referenceSymbols: SymbolAndEntries[]): Entry[] {
@@ -257,7 +260,7 @@ namespace ts.FindAllReferences {
/* @internal */
namespace ts.FindAllReferences.Core {
/** Core find-all-references algorithm. Handles special cases before delegating to `getReferencedSymbolsForSymbol`. */
export function getReferencedSymbolsForNode(node: Node, sourceFiles: SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken, options: Options = {}): SymbolAndEntries[] | undefined {
export function getReferencedSymbolsForNode(node: Node, program: Program, sourceFiles: SourceFile[], cancellationToken: CancellationToken, options: Options = {}): SymbolAndEntries[] | undefined {
if (node.kind === ts.SyntaxKind.SourceFile) {
return undefined;
}
@@ -269,6 +272,7 @@ namespace ts.FindAllReferences.Core {
}
}
const checker = program.getTypeChecker();
const symbol = checker.getSymbolAtLocation(node);
// Could not find a symbol e.g. unknown identifier
@@ -281,9 +285,65 @@ namespace ts.FindAllReferences.Core {
return undefined;
}
if (symbol.flags & SymbolFlags.Module && isModuleReferenceLocation(node)) {
return getReferencedSymbolsForModule(program, symbol, sourceFiles);
}
return getReferencedSymbolsForSymbol(symbol, node, sourceFiles, checker, cancellationToken, options);
}
function isModuleReferenceLocation(node: ts.Node): boolean {
if (node.kind !== SyntaxKind.StringLiteral) {
return false;
}
switch (node.parent.kind) {
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ExternalModuleReference:
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ExportDeclaration:
return true;
case SyntaxKind.CallExpression:
return isRequireCall(node.parent as CallExpression, /*checkArgumentIsStringLiteral*/ false);
default:
return false;
}
}
function getReferencedSymbolsForModule(program: Program, symbol: Symbol, sourceFiles: SourceFile[]): SymbolAndEntries[] {
Debug.assert(!!symbol.valueDeclaration);
const references = findModuleReferences(program, sourceFiles, symbol).map<Entry>(reference => {
if (reference.kind === "import") {
return { type: "node", node: reference.literal };
}
else {
return {
type: "span",
fileName: reference.referencingFile.fileName,
textSpan: createTextSpanFromRange(reference.ref),
};
}
});
for (const decl of symbol.declarations) {
switch (decl.kind) {
case ts.SyntaxKind.SourceFile:
// Don't include the source file itself. (This may not be ideal behavior, but awkward to include an entire file as a reference.)
break;
case ts.SyntaxKind.ModuleDeclaration:
references.push({ type: "node", node: (decl as ts.ModuleDeclaration).name });
break;
default:
Debug.fail("Expected a module symbol to be declared by a SourceFile or ModuleDeclaration.");
}
}
return [{
definition: { type: "symbol", symbol, node: symbol.valueDeclaration },
references
}];
}
/** getReferencedSymbols for special node kinds. */
function getReferencedSymbolsSpecial(node: Node, sourceFiles: SourceFile[], cancellationToken: CancellationToken): SymbolAndEntries[] | undefined {
if (isTypeKeyword(node.kind)) {

View File

@@ -263,7 +263,7 @@ namespace ts.GoToDefinition {
function findReferenceInPosition(refs: FileReference[], pos: number): FileReference {
for (const ref of refs) {
if (ref.pos <= pos && pos < ref.end) {
if (ref.pos <= pos && pos <= ref.end) {
return ref;
}
}

View File

@@ -300,6 +300,40 @@ namespace ts.FindAllReferences {
});
}
type ModuleReference =
/** "import" also includes require() calls. */
| { kind: "import", literal: StringLiteral }
/** <reference path> or <reference types> */
| { kind: "reference", referencingFile: SourceFile, ref: FileReference };
export function findModuleReferences(program: Program, sourceFiles: SourceFile[], searchModuleSymbol: Symbol): ModuleReference[] {
const refs: ModuleReference[] = [];
const checker = program.getTypeChecker();
for (const referencingFile of sourceFiles) {
const searchSourceFile = searchModuleSymbol.valueDeclaration;
if (searchSourceFile.kind === ts.SyntaxKind.SourceFile) {
for (const ref of referencingFile.referencedFiles) {
if (program.getSourceFileFromReference(referencingFile, ref) === searchSourceFile) {
refs.push({ kind: "reference", referencingFile, ref });
}
}
for (const ref of referencingFile.typeReferenceDirectives) {
const referenced = program.getResolvedTypeReferenceDirectives().get(ref.fileName);
if (referenced !== undefined && referenced.resolvedFileName === (searchSourceFile as ts.SourceFile).fileName) {
refs.push({ kind: "reference", referencingFile, ref });
}
}
}
forEachImport(referencingFile, (_importDecl, moduleSpecifier) => {
const moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier);
if (moduleSymbol === searchModuleSymbol) {
refs.push({ kind: "import", literal: moduleSpecifier });
}
});
}
return refs;
}
/** Returns a map from a module symbol Id to all import statements that directly reference the module. */
function getDirectImportsMap(sourceFiles: SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken): Map<ImporterOrCallExpression[]> {
const map = createMap<ImporterOrCallExpression[]>();
@@ -371,7 +405,7 @@ namespace ts.FindAllReferences {
case SyntaxKind.ExternalModuleReference:
return (decl as ExternalModuleReference).parent;
default:
Debug.assert(false);
Debug.fail(`Unexpected module specifier parent: ${decl.kind}`);
}
}

View File

@@ -1417,7 +1417,7 @@ namespace ts {
/// Goto implementation
function getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] {
synchronizeHostData();
return FindAllReferences.getImplementationsAtPosition(program.getTypeChecker(), cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position);
return FindAllReferences.getImplementationsAtPosition(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position);
}
/// References and Occurrences
@@ -1439,7 +1439,7 @@ namespace ts {
synchronizeHostData();
const sourceFilesToSearch = map(filesToSearch, f => program.getSourceFile(f));
const sourceFile = getValidSourceFile(fileName);
return DocumentHighlights.getDocumentHighlights(program.getTypeChecker(), cancellationToken, sourceFile, position, sourceFilesToSearch);
return DocumentHighlights.getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch);
}
function getOccurrencesAtPositionCore(fileName: string, position: number): ReferenceEntry[] {
@@ -1477,12 +1477,12 @@ namespace ts {
function getReferences(fileName: string, position: number, options?: FindAllReferences.Options) {
synchronizeHostData();
return FindAllReferences.findReferencedEntries(program.getTypeChecker(), cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position, options);
return FindAllReferences.findReferencedEntries(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position, options);
}
function findReferences(fileName: string, position: number): ReferencedSymbol[] {
synchronizeHostData();
return FindAllReferences.findReferencedSymbols(program.getTypeChecker(), cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position);
return FindAllReferences.findReferencedSymbols(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position);
}
/// NavigateTo

View File

@@ -1066,6 +1066,10 @@ namespace ts {
return createTextSpanFromBounds(node.getStart(sourceFile), node.getEnd());
}
export function createTextSpanFromRange(range: TextRange): TextSpan {
return createTextSpanFromBounds(range.pos, range.end);
}
export function isTypeKeyword(kind: SyntaxKind): boolean {
switch (kind) {
case SyntaxKind.AnyKeyword: