Merge pull request #2682 from Microsoft/GetOccurrencesSingleFile
Ensure that getOccurrences not return items not in the file asked for.
This commit is contained in:
commit
97a3e71dc7
|
@ -336,6 +336,9 @@ module Harness.LanguageService {
|
||||||
getOccurrencesAtPosition(fileName: string, position: number): ts.ReferenceEntry[] {
|
getOccurrencesAtPosition(fileName: string, position: number): ts.ReferenceEntry[] {
|
||||||
return unwrapJSONCallResult(this.shim.getOccurrencesAtPosition(fileName, position));
|
return unwrapJSONCallResult(this.shim.getOccurrencesAtPosition(fileName, position));
|
||||||
}
|
}
|
||||||
|
getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): ts.DocumentHighlights[] {
|
||||||
|
return unwrapJSONCallResult(this.shim.getDocumentHighlights(fileName, position, JSON.stringify(filesToSearch)));
|
||||||
|
}
|
||||||
getNavigateToItems(searchValue: string): ts.NavigateToItem[] {
|
getNavigateToItems(searchValue: string): ts.NavigateToItem[] {
|
||||||
return unwrapJSONCallResult(this.shim.getNavigateToItems(searchValue));
|
return unwrapJSONCallResult(this.shim.getNavigateToItems(searchValue));
|
||||||
}
|
}
|
||||||
|
|
|
@ -488,6 +488,10 @@ module ts.server {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDocumentHighlights(fileName: string, position: number): DocumentHighlights[] {
|
||||||
|
throw new Error("Not Implemented Yet.");
|
||||||
|
}
|
||||||
|
|
||||||
getOutliningSpans(fileName: string): OutliningSpan[] {
|
getOutliningSpans(fileName: string): OutliningSpan[] {
|
||||||
throw new Error("Not Implemented Yet.");
|
throw new Error("Not Implemented Yet.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -944,8 +944,11 @@ module ts {
|
||||||
|
|
||||||
getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
|
getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
|
||||||
getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[];
|
getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[];
|
||||||
getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[];
|
|
||||||
findReferences(fileName: string, position: number): ReferencedSymbol[];
|
findReferences(fileName: string, position: number): ReferencedSymbol[];
|
||||||
|
getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[];
|
||||||
|
|
||||||
|
/** @deprecated */
|
||||||
|
getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[];
|
||||||
|
|
||||||
getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[];
|
getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[];
|
||||||
getNavigationBarItems(fileName: string): NavigationBarItem[];
|
getNavigationBarItems(fileName: string): NavigationBarItem[];
|
||||||
|
@ -1011,6 +1014,23 @@ module ts {
|
||||||
isWriteAccess: boolean;
|
isWriteAccess: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DocumentHighlights {
|
||||||
|
fileName: string;
|
||||||
|
highlightSpans: HighlightSpan[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export module DocumentHighlightKind {
|
||||||
|
export const none = "none";
|
||||||
|
export const definition = "definition";
|
||||||
|
export const reference = "reference";
|
||||||
|
export const writtenReference = "writtenReference";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HighlightSpan {
|
||||||
|
textSpan: TextSpan;
|
||||||
|
kind: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface NavigateToItem {
|
export interface NavigateToItem {
|
||||||
name: string;
|
name: string;
|
||||||
kind: string;
|
kind: string;
|
||||||
|
@ -1315,92 +1335,92 @@ module ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move these to enums
|
// TODO: move these to enums
|
||||||
export class ScriptElementKind {
|
export module ScriptElementKind {
|
||||||
static unknown = "";
|
export const unknown = "";
|
||||||
static warning = "warning";
|
export const warning = "warning";
|
||||||
|
|
||||||
// predefined type (void) or keyword (class)
|
// predefined type (void) or keyword (class)
|
||||||
static keyword = "keyword";
|
export const keyword = "keyword";
|
||||||
|
|
||||||
// top level script node
|
// top level script node
|
||||||
static scriptElement = "script";
|
export const scriptElement = "script";
|
||||||
|
|
||||||
// module foo {}
|
// module foo {}
|
||||||
static moduleElement = "module";
|
export const moduleElement = "module";
|
||||||
|
|
||||||
// class X {}
|
// class X {}
|
||||||
static classElement = "class";
|
export const classElement = "class";
|
||||||
|
|
||||||
// interface Y {}
|
// interface Y {}
|
||||||
static interfaceElement = "interface";
|
export const interfaceElement = "interface";
|
||||||
|
|
||||||
// type T = ...
|
// type T = ...
|
||||||
static typeElement = "type";
|
export const typeElement = "type";
|
||||||
|
|
||||||
// enum E
|
// enum E
|
||||||
static enumElement = "enum";
|
export const enumElement = "enum";
|
||||||
|
|
||||||
// Inside module and script only
|
// Inside module and script only
|
||||||
// let v = ..
|
// let v = ..
|
||||||
static variableElement = "var";
|
export const variableElement = "var";
|
||||||
|
|
||||||
// Inside function
|
// Inside function
|
||||||
static localVariableElement = "local var";
|
export const localVariableElement = "local var";
|
||||||
|
|
||||||
// Inside module and script only
|
// Inside module and script only
|
||||||
// function f() { }
|
// function f() { }
|
||||||
static functionElement = "function";
|
export const functionElement = "function";
|
||||||
|
|
||||||
// Inside function
|
// Inside function
|
||||||
static localFunctionElement = "local function";
|
export const localFunctionElement = "local function";
|
||||||
|
|
||||||
// class X { [public|private]* foo() {} }
|
// class X { [public|private]* foo() {} }
|
||||||
static memberFunctionElement = "method";
|
export const memberFunctionElement = "method";
|
||||||
|
|
||||||
// class X { [public|private]* [get|set] foo:number; }
|
// class X { [public|private]* [get|set] foo:number; }
|
||||||
static memberGetAccessorElement = "getter";
|
export const memberGetAccessorElement = "getter";
|
||||||
static memberSetAccessorElement = "setter";
|
export const memberSetAccessorElement = "setter";
|
||||||
|
|
||||||
// class X { [public|private]* foo:number; }
|
// class X { [public|private]* foo:number; }
|
||||||
// interface Y { foo:number; }
|
// interface Y { foo:number; }
|
||||||
static memberVariableElement = "property";
|
export const memberVariableElement = "property";
|
||||||
|
|
||||||
// class X { constructor() { } }
|
// class X { constructor() { } }
|
||||||
static constructorImplementationElement = "constructor";
|
export const constructorImplementationElement = "constructor";
|
||||||
|
|
||||||
// interface Y { ():number; }
|
// interface Y { ():number; }
|
||||||
static callSignatureElement = "call";
|
export const callSignatureElement = "call";
|
||||||
|
|
||||||
// interface Y { []:number; }
|
// interface Y { []:number; }
|
||||||
static indexSignatureElement = "index";
|
export const indexSignatureElement = "index";
|
||||||
|
|
||||||
// interface Y { new():Y; }
|
// interface Y { new():Y; }
|
||||||
static constructSignatureElement = "construct";
|
export const constructSignatureElement = "construct";
|
||||||
|
|
||||||
// function foo(*Y*: string)
|
// function foo(*Y*: string)
|
||||||
static parameterElement = "parameter";
|
export const parameterElement = "parameter";
|
||||||
|
|
||||||
static typeParameterElement = "type parameter";
|
export const typeParameterElement = "type parameter";
|
||||||
|
|
||||||
static primitiveType = "primitive type";
|
export const primitiveType = "primitive type";
|
||||||
|
|
||||||
static label = "label";
|
export const label = "label";
|
||||||
|
|
||||||
static alias = "alias";
|
export const alias = "alias";
|
||||||
|
|
||||||
static constElement = "const";
|
export const constElement = "const";
|
||||||
|
|
||||||
static letElement = "let";
|
export const letElement = "let";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ScriptElementKindModifier {
|
export module ScriptElementKindModifier {
|
||||||
static none = "";
|
export const none = "";
|
||||||
static publicMemberModifier = "public";
|
export const publicMemberModifier = "public";
|
||||||
static privateMemberModifier = "private";
|
export const privateMemberModifier = "private";
|
||||||
static protectedMemberModifier = "protected";
|
export const protectedMemberModifier = "protected";
|
||||||
static exportedModifier = "export";
|
export const exportedModifier = "export";
|
||||||
static ambientModifier = "declare";
|
export const ambientModifier = "declare";
|
||||||
static staticModifier = "static";
|
export const staticModifier = "static";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ClassificationTypeNames {
|
export class ClassificationTypeNames {
|
||||||
|
@ -3961,20 +3981,19 @@ module ts {
|
||||||
if (results) {
|
if (results) {
|
||||||
let sourceFile = getCanonicalFileName(normalizeSlashes(fileName));
|
let sourceFile = getCanonicalFileName(normalizeSlashes(fileName));
|
||||||
|
|
||||||
// ensure the results are in the file we're interested in
|
// Get occurrences only supports reporting occurrences for the file queried. So
|
||||||
results.forEach((value) => {
|
// filter down to that list.
|
||||||
let targetFile = getCanonicalFileName(normalizeSlashes(value.fileName));
|
results = filter(results, r => r.fileName === fileName);
|
||||||
Debug.assert(sourceFile == targetFile, `Unexpected file in results. Found results in ${targetFile} expected only results in ${sourceFile}.`);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// References and Occurrences
|
function getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] {
|
||||||
function getOccurrencesAtPositionCore(fileName: string, position: number): ReferenceEntry[] {
|
|
||||||
synchronizeHostData();
|
synchronizeHostData();
|
||||||
|
|
||||||
|
filesToSearch = map(filesToSearch, normalizeSlashes);
|
||||||
|
let sourceFilesToSearch = filter(program.getSourceFiles(), f => contains(filesToSearch, f.fileName));
|
||||||
let sourceFile = getValidSourceFile(fileName);
|
let sourceFile = getValidSourceFile(fileName);
|
||||||
|
|
||||||
let node = getTouchingWord(sourceFile, position);
|
let node = getTouchingWord(sourceFile, position);
|
||||||
|
@ -3982,11 +4001,83 @@ module ts {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.ThisKeyword || node.kind === SyntaxKind.SuperKeyword ||
|
return getSemanticDocumentHighlights(node) || getSyntacticDocumentHighlights(node);
|
||||||
isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) {
|
|
||||||
return convertReferences(getReferencesForNode(node, [sourceFile], /*searchOnlyInCurrentFile*/ true, /*findInStrings:*/ false, /*findInComments:*/ false));
|
function getHighlightSpanForNode(node: Node): HighlightSpan {
|
||||||
|
let start = node.getStart();
|
||||||
|
let end = node.getEnd();
|
||||||
|
|
||||||
|
return {
|
||||||
|
fileName: sourceFile.fileName,
|
||||||
|
textSpan: createTextSpanFromBounds(start, end),
|
||||||
|
kind: DocumentHighlightKind.none
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSemanticDocumentHighlights(node: Node): DocumentHighlights[] {
|
||||||
|
if (node.kind === SyntaxKind.Identifier ||
|
||||||
|
node.kind === SyntaxKind.ThisKeyword ||
|
||||||
|
node.kind === SyntaxKind.SuperKeyword ||
|
||||||
|
isLiteralNameOfPropertyDeclarationOrIndexAccess(node) ||
|
||||||
|
isNameOfExternalModuleImportOrDeclaration(node)) {
|
||||||
|
|
||||||
|
let referencedSymbols = getReferencedSymbolsForNodes(node, sourceFilesToSearch, /*findInStrings:*/ false, /*findInComments:*/ false);
|
||||||
|
return convertReferencedSymbols(referencedSymbols);
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
|
||||||
|
function convertReferencedSymbols(referencedSymbols: ReferencedSymbol[]): DocumentHighlights[] {
|
||||||
|
if (!referencedSymbols) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
let fileNameToDocumentHighlights: Map<DocumentHighlights> = {};
|
||||||
|
let result: DocumentHighlights[] = [];
|
||||||
|
for (let referencedSymbol of referencedSymbols) {
|
||||||
|
for (let referenceEntry of referencedSymbol.references) {
|
||||||
|
let fileName = referenceEntry.fileName;
|
||||||
|
let documentHighlights = getProperty(fileNameToDocumentHighlights, fileName);
|
||||||
|
if (!documentHighlights) {
|
||||||
|
documentHighlights = { fileName, highlightSpans: [] };
|
||||||
|
|
||||||
|
fileNameToDocumentHighlights[fileName] = documentHighlights;
|
||||||
|
result.push(documentHighlights);
|
||||||
|
}
|
||||||
|
|
||||||
|
documentHighlights.highlightSpans.push({
|
||||||
|
textSpan: referenceEntry.textSpan,
|
||||||
|
kind: referenceEntry.isWriteAccess ? DocumentHighlightKind.writtenReference : DocumentHighlightKind.reference
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSyntacticDocumentHighlights(node: Node): DocumentHighlights[] {
|
||||||
|
let fileName = sourceFile.fileName;
|
||||||
|
|
||||||
|
var highlightSpans = getHighlightSpans(node);
|
||||||
|
if (!highlightSpans || highlightSpans.length === 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [{ fileName, highlightSpans }];
|
||||||
|
|
||||||
|
// returns true if 'node' is defined and has a matching 'kind'.
|
||||||
|
function hasKind(node: Node, kind: SyntaxKind) {
|
||||||
|
return node !== undefined && node.kind === kind;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Null-propagating 'parent' function.
|
||||||
|
function parent(node: Node): Node {
|
||||||
|
return node && node.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHighlightSpans(node: Node): HighlightSpan[] {
|
||||||
|
if (node) {
|
||||||
switch (node.kind) {
|
switch (node.kind) {
|
||||||
case SyntaxKind.IfKeyword:
|
case SyntaxKind.IfKeyword:
|
||||||
case SyntaxKind.ElseKeyword:
|
case SyntaxKind.ElseKeyword:
|
||||||
|
@ -4061,116 +4152,9 @@ module ts {
|
||||||
return getModifierOccurrences(node.kind, node.parent);
|
return getModifierOccurrences(node.kind, node.parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
||||||
function getIfElseOccurrences(ifStatement: IfStatement): ReferenceEntry[] {
|
|
||||||
let keywords: Node[] = [];
|
|
||||||
|
|
||||||
// Traverse upwards through all parent if-statements linked by their else-branches.
|
|
||||||
while (hasKind(ifStatement.parent, SyntaxKind.IfStatement) && (<IfStatement>ifStatement.parent).elseStatement === ifStatement) {
|
|
||||||
ifStatement = <IfStatement>ifStatement.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now traverse back down through the else branches, aggregating if/else keywords of if-statements.
|
|
||||||
while (ifStatement) {
|
|
||||||
let children = ifStatement.getChildren();
|
|
||||||
pushKeywordIf(keywords, children[0], SyntaxKind.IfKeyword);
|
|
||||||
|
|
||||||
// Generally the 'else' keyword is second-to-last, so we traverse backwards.
|
|
||||||
for (let i = children.length - 1; i >= 0; i--) {
|
|
||||||
if (pushKeywordIf(keywords, children[i], SyntaxKind.ElseKeyword)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasKind(ifStatement.elseStatement, SyntaxKind.IfStatement)) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
ifStatement = <IfStatement>ifStatement.elseStatement;
|
|
||||||
}
|
|
||||||
|
|
||||||
let result: ReferenceEntry[] = [];
|
|
||||||
|
|
||||||
// We'd like to highlight else/ifs together if they are only separated by whitespace
|
|
||||||
// (i.e. the keywords are separated by no comments, no newlines).
|
|
||||||
for (let i = 0; i < keywords.length; i++) {
|
|
||||||
if (keywords[i].kind === SyntaxKind.ElseKeyword && i < keywords.length - 1) {
|
|
||||||
let elseKeyword = keywords[i];
|
|
||||||
let ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword.
|
|
||||||
|
|
||||||
let shouldHighlightNextKeyword = true;
|
|
||||||
|
|
||||||
// Avoid recalculating getStart() by iterating backwards.
|
|
||||||
for (let j = ifKeyword.getStart() - 1; j >= elseKeyword.end; j--) {
|
|
||||||
if (!isWhiteSpace(sourceFile.text.charCodeAt(j))) {
|
|
||||||
shouldHighlightNextKeyword = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldHighlightNextKeyword) {
|
|
||||||
result.push({
|
|
||||||
fileName: fileName,
|
|
||||||
textSpan: createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end),
|
|
||||||
isWriteAccess: false
|
|
||||||
});
|
|
||||||
i++; // skip the next keyword
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ordinary case: just highlight the keyword.
|
|
||||||
result.push(getReferenceEntryFromNode(keywords[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getReturnOccurrences(returnStatement: ReturnStatement): ReferenceEntry[] {
|
|
||||||
let func = <FunctionLikeDeclaration>getContainingFunction(returnStatement);
|
|
||||||
|
|
||||||
// If we didn't find a containing function with a block body, bail out.
|
|
||||||
if (!(func && hasKind(func.body, SyntaxKind.Block))) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
let keywords: Node[] = []
|
|
||||||
forEachReturnStatement(<Block>func.body, returnStatement => {
|
|
||||||
pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Include 'throw' statements that do not occur within a try block.
|
|
||||||
forEach(aggregateOwnedThrowStatements(func.body), throwStatement => {
|
|
||||||
pushKeywordIf(keywords, throwStatement.getFirstToken(), SyntaxKind.ThrowKeyword);
|
|
||||||
});
|
|
||||||
|
|
||||||
return map(keywords, getReferenceEntryFromNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getThrowOccurrences(throwStatement: ThrowStatement) {
|
|
||||||
let owner = getThrowStatementOwner(throwStatement);
|
|
||||||
|
|
||||||
if (!owner) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
let keywords: Node[] = [];
|
|
||||||
|
|
||||||
forEach(aggregateOwnedThrowStatements(owner), throwStatement => {
|
|
||||||
pushKeywordIf(keywords, throwStatement.getFirstToken(), SyntaxKind.ThrowKeyword);
|
|
||||||
});
|
|
||||||
|
|
||||||
// If the "owner" is a function, then we equate 'return' and 'throw' statements in their
|
|
||||||
// ability to "jump out" of the function, and include occurrences for both.
|
|
||||||
if (isFunctionBlock(owner)) {
|
|
||||||
forEachReturnStatement(<Block>owner, returnStatement => {
|
|
||||||
pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return map(keywords, getReferenceEntryFromNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4240,91 +4224,6 @@ module ts {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTryCatchFinallyOccurrences(tryStatement: TryStatement): ReferenceEntry[] {
|
|
||||||
let keywords: Node[] = [];
|
|
||||||
|
|
||||||
pushKeywordIf(keywords, tryStatement.getFirstToken(), SyntaxKind.TryKeyword);
|
|
||||||
|
|
||||||
if (tryStatement.catchClause) {
|
|
||||||
pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), SyntaxKind.CatchKeyword);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tryStatement.finallyBlock) {
|
|
||||||
let finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile);
|
|
||||||
pushKeywordIf(keywords, finallyKeyword, SyntaxKind.FinallyKeyword);
|
|
||||||
}
|
|
||||||
|
|
||||||
return map(keywords, getReferenceEntryFromNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLoopBreakContinueOccurrences(loopNode: IterationStatement): ReferenceEntry[] {
|
|
||||||
let keywords: Node[] = [];
|
|
||||||
|
|
||||||
if (pushKeywordIf(keywords, loopNode.getFirstToken(), SyntaxKind.ForKeyword, SyntaxKind.WhileKeyword, SyntaxKind.DoKeyword)) {
|
|
||||||
// If we succeeded and got a do-while loop, then start looking for a 'while' keyword.
|
|
||||||
if (loopNode.kind === SyntaxKind.DoStatement) {
|
|
||||||
let loopTokens = loopNode.getChildren();
|
|
||||||
|
|
||||||
for (let i = loopTokens.length - 1; i >= 0; i--) {
|
|
||||||
if (pushKeywordIf(keywords, loopTokens[i], SyntaxKind.WhileKeyword)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement);
|
|
||||||
|
|
||||||
forEach(breaksAndContinues, statement => {
|
|
||||||
if (ownsBreakOrContinueStatement(loopNode, statement)) {
|
|
||||||
pushKeywordIf(keywords, statement.getFirstToken(), SyntaxKind.BreakKeyword, SyntaxKind.ContinueKeyword);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return map(keywords, getReferenceEntryFromNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement): ReferenceEntry[] {
|
|
||||||
let keywords: Node[] = [];
|
|
||||||
|
|
||||||
pushKeywordIf(keywords, switchStatement.getFirstToken(), SyntaxKind.SwitchKeyword);
|
|
||||||
|
|
||||||
// Go through each clause in the switch statement, collecting the 'case'/'default' keywords.
|
|
||||||
forEach(switchStatement.caseBlock.clauses, clause => {
|
|
||||||
pushKeywordIf(keywords, clause.getFirstToken(), SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword);
|
|
||||||
|
|
||||||
let breaksAndContinues = aggregateAllBreakAndContinueStatements(clause);
|
|
||||||
|
|
||||||
forEach(breaksAndContinues, statement => {
|
|
||||||
if (ownsBreakOrContinueStatement(switchStatement, statement)) {
|
|
||||||
pushKeywordIf(keywords, statement.getFirstToken(), SyntaxKind.BreakKeyword);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return map(keywords, getReferenceEntryFromNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBreakOrContinueStatementOccurences(breakOrContinueStatement: BreakOrContinueStatement): ReferenceEntry[] {
|
|
||||||
let owner = getBreakOrContinueOwner(breakOrContinueStatement);
|
|
||||||
|
|
||||||
if (owner) {
|
|
||||||
switch (owner.kind) {
|
|
||||||
case SyntaxKind.ForStatement:
|
|
||||||
case SyntaxKind.ForInStatement:
|
|
||||||
case SyntaxKind.ForOfStatement:
|
|
||||||
case SyntaxKind.DoStatement:
|
|
||||||
case SyntaxKind.WhileStatement:
|
|
||||||
return getLoopBreakContinueOccurrences(<IterationStatement>owner)
|
|
||||||
case SyntaxKind.SwitchStatement:
|
|
||||||
return getSwitchCaseDefaultOccurrences(<SwitchStatement>owner);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function aggregateAllBreakAndContinueStatements(node: Node): BreakOrContinueStatement[] {
|
function aggregateAllBreakAndContinueStatements(node: Node): BreakOrContinueStatement[] {
|
||||||
let statementAccumulator: BreakOrContinueStatement[] = []
|
let statementAccumulator: BreakOrContinueStatement[] = []
|
||||||
aggregate(node);
|
aggregate(node);
|
||||||
|
@ -4376,38 +4275,7 @@ module ts {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getConstructorOccurrences(constructorDeclaration: ConstructorDeclaration): ReferenceEntry[] {
|
function getModifierOccurrences(modifier: SyntaxKind, declaration: Node): HighlightSpan[] {
|
||||||
let declarations = constructorDeclaration.symbol.getDeclarations()
|
|
||||||
|
|
||||||
let keywords: Node[] = [];
|
|
||||||
|
|
||||||
forEach(declarations, declaration => {
|
|
||||||
forEach(declaration.getChildren(), token => {
|
|
||||||
return pushKeywordIf(keywords, token, SyntaxKind.ConstructorKeyword);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return map(keywords, getReferenceEntryFromNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getGetAndSetOccurrences(accessorDeclaration: AccessorDeclaration): ReferenceEntry[] {
|
|
||||||
let keywords: Node[] = [];
|
|
||||||
|
|
||||||
tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.GetAccessor);
|
|
||||||
tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.SetAccessor);
|
|
||||||
|
|
||||||
return map(keywords, getReferenceEntryFromNode);
|
|
||||||
|
|
||||||
function tryPushAccessorKeyword(accessorSymbol: Symbol, accessorKind: SyntaxKind): void {
|
|
||||||
let accessor = getDeclarationOfKind(accessorSymbol, accessorKind);
|
|
||||||
|
|
||||||
if (accessor) {
|
|
||||||
forEach(accessor.getChildren(), child => pushKeywordIf(keywords, child, SyntaxKind.GetKeyword, SyntaxKind.SetKeyword));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getModifierOccurrences(modifier: SyntaxKind, declaration: Node): ReferenceEntry[] {
|
|
||||||
let container = declaration.parent;
|
let container = declaration.parent;
|
||||||
|
|
||||||
// Make sure we only highlight the keyword when it makes sense to do so.
|
// Make sure we only highlight the keyword when it makes sense to do so.
|
||||||
|
@ -4470,7 +4338,7 @@ module ts {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return map(keywords, getReferenceEntryFromNode);
|
return map(keywords, getHighlightSpanForNode);
|
||||||
|
|
||||||
function getFlagFromModifier(modifier: SyntaxKind) {
|
function getFlagFromModifier(modifier: SyntaxKind) {
|
||||||
switch (modifier) {
|
switch (modifier) {
|
||||||
|
@ -4492,16 +4360,6 @@ module ts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if 'node' is defined and has a matching 'kind'.
|
|
||||||
function hasKind(node: Node, kind: SyntaxKind) {
|
|
||||||
return node !== undefined && node.kind === kind;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Null-propagating 'parent' function.
|
|
||||||
function parent(node: Node): Node {
|
|
||||||
return node && node.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
function pushKeywordIf(keywordList: Node[], token: Node, ...expected: SyntaxKind[]): boolean {
|
function pushKeywordIf(keywordList: Node[], token: Node, ...expected: SyntaxKind[]): boolean {
|
||||||
if (token && contains(expected, token.kind)) {
|
if (token && contains(expected, token.kind)) {
|
||||||
keywordList.push(token);
|
keywordList.push(token);
|
||||||
|
@ -4510,6 +4368,258 @@ module ts {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getGetAndSetOccurrences(accessorDeclaration: AccessorDeclaration): HighlightSpan[] {
|
||||||
|
let keywords: Node[] = [];
|
||||||
|
|
||||||
|
tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.GetAccessor);
|
||||||
|
tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.SetAccessor);
|
||||||
|
|
||||||
|
return map(keywords, getHighlightSpanForNode);
|
||||||
|
|
||||||
|
function tryPushAccessorKeyword(accessorSymbol: Symbol, accessorKind: SyntaxKind): void {
|
||||||
|
let accessor = getDeclarationOfKind(accessorSymbol, accessorKind);
|
||||||
|
|
||||||
|
if (accessor) {
|
||||||
|
forEach(accessor.getChildren(), child => pushKeywordIf(keywords, child, SyntaxKind.GetKeyword, SyntaxKind.SetKeyword));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getConstructorOccurrences(constructorDeclaration: ConstructorDeclaration): HighlightSpan[] {
|
||||||
|
let declarations = constructorDeclaration.symbol.getDeclarations()
|
||||||
|
|
||||||
|
let keywords: Node[] = [];
|
||||||
|
|
||||||
|
forEach(declarations, declaration => {
|
||||||
|
forEach(declaration.getChildren(), token => {
|
||||||
|
return pushKeywordIf(keywords, token, SyntaxKind.ConstructorKeyword);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return map(keywords, getHighlightSpanForNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLoopBreakContinueOccurrences(loopNode: IterationStatement): HighlightSpan[] {
|
||||||
|
let keywords: Node[] = [];
|
||||||
|
|
||||||
|
if (pushKeywordIf(keywords, loopNode.getFirstToken(), SyntaxKind.ForKeyword, SyntaxKind.WhileKeyword, SyntaxKind.DoKeyword)) {
|
||||||
|
// If we succeeded and got a do-while loop, then start looking for a 'while' keyword.
|
||||||
|
if (loopNode.kind === SyntaxKind.DoStatement) {
|
||||||
|
let loopTokens = loopNode.getChildren();
|
||||||
|
|
||||||
|
for (let i = loopTokens.length - 1; i >= 0; i--) {
|
||||||
|
if (pushKeywordIf(keywords, loopTokens[i], SyntaxKind.WhileKeyword)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement);
|
||||||
|
|
||||||
|
forEach(breaksAndContinues, statement => {
|
||||||
|
if (ownsBreakOrContinueStatement(loopNode, statement)) {
|
||||||
|
pushKeywordIf(keywords, statement.getFirstToken(), SyntaxKind.BreakKeyword, SyntaxKind.ContinueKeyword);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return map(keywords, getHighlightSpanForNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBreakOrContinueStatementOccurences(breakOrContinueStatement: BreakOrContinueStatement): HighlightSpan[] {
|
||||||
|
let owner = getBreakOrContinueOwner(breakOrContinueStatement);
|
||||||
|
|
||||||
|
if (owner) {
|
||||||
|
switch (owner.kind) {
|
||||||
|
case SyntaxKind.ForStatement:
|
||||||
|
case SyntaxKind.ForInStatement:
|
||||||
|
case SyntaxKind.ForOfStatement:
|
||||||
|
case SyntaxKind.DoStatement:
|
||||||
|
case SyntaxKind.WhileStatement:
|
||||||
|
return getLoopBreakContinueOccurrences(<IterationStatement>owner)
|
||||||
|
case SyntaxKind.SwitchStatement:
|
||||||
|
return getSwitchCaseDefaultOccurrences(<SwitchStatement>owner);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement): HighlightSpan[] {
|
||||||
|
let keywords: Node[] = [];
|
||||||
|
|
||||||
|
pushKeywordIf(keywords, switchStatement.getFirstToken(), SyntaxKind.SwitchKeyword);
|
||||||
|
|
||||||
|
// Go through each clause in the switch statement, collecting the 'case'/'default' keywords.
|
||||||
|
forEach(switchStatement.caseBlock.clauses, clause => {
|
||||||
|
pushKeywordIf(keywords, clause.getFirstToken(), SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword);
|
||||||
|
|
||||||
|
let breaksAndContinues = aggregateAllBreakAndContinueStatements(clause);
|
||||||
|
|
||||||
|
forEach(breaksAndContinues, statement => {
|
||||||
|
if (ownsBreakOrContinueStatement(switchStatement, statement)) {
|
||||||
|
pushKeywordIf(keywords, statement.getFirstToken(), SyntaxKind.BreakKeyword);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return map(keywords, getHighlightSpanForNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTryCatchFinallyOccurrences(tryStatement: TryStatement): HighlightSpan[] {
|
||||||
|
let keywords: Node[] = [];
|
||||||
|
|
||||||
|
pushKeywordIf(keywords, tryStatement.getFirstToken(), SyntaxKind.TryKeyword);
|
||||||
|
|
||||||
|
if (tryStatement.catchClause) {
|
||||||
|
pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), SyntaxKind.CatchKeyword);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tryStatement.finallyBlock) {
|
||||||
|
let finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile);
|
||||||
|
pushKeywordIf(keywords, finallyKeyword, SyntaxKind.FinallyKeyword);
|
||||||
|
}
|
||||||
|
|
||||||
|
return map(keywords, getHighlightSpanForNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getThrowOccurrences(throwStatement: ThrowStatement): HighlightSpan[] {
|
||||||
|
let owner = getThrowStatementOwner(throwStatement);
|
||||||
|
|
||||||
|
if (!owner) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
let keywords: Node[] = [];
|
||||||
|
|
||||||
|
forEach(aggregateOwnedThrowStatements(owner), throwStatement => {
|
||||||
|
pushKeywordIf(keywords, throwStatement.getFirstToken(), SyntaxKind.ThrowKeyword);
|
||||||
|
});
|
||||||
|
|
||||||
|
// If the "owner" is a function, then we equate 'return' and 'throw' statements in their
|
||||||
|
// ability to "jump out" of the function, and include occurrences for both.
|
||||||
|
if (isFunctionBlock(owner)) {
|
||||||
|
forEachReturnStatement(<Block>owner, returnStatement => {
|
||||||
|
pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return map(keywords, getHighlightSpanForNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getReturnOccurrences(returnStatement: ReturnStatement): HighlightSpan[] {
|
||||||
|
let func = <FunctionLikeDeclaration>getContainingFunction(returnStatement);
|
||||||
|
|
||||||
|
// If we didn't find a containing function with a block body, bail out.
|
||||||
|
if (!(func && hasKind(func.body, SyntaxKind.Block))) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
let keywords: Node[] = []
|
||||||
|
forEachReturnStatement(<Block>func.body, returnStatement => {
|
||||||
|
pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Include 'throw' statements that do not occur within a try block.
|
||||||
|
forEach(aggregateOwnedThrowStatements(func.body), throwStatement => {
|
||||||
|
pushKeywordIf(keywords, throwStatement.getFirstToken(), SyntaxKind.ThrowKeyword);
|
||||||
|
});
|
||||||
|
|
||||||
|
return map(keywords, getHighlightSpanForNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIfElseOccurrences(ifStatement: IfStatement): HighlightSpan[] {
|
||||||
|
let keywords: Node[] = [];
|
||||||
|
|
||||||
|
// Traverse upwards through all parent if-statements linked by their else-branches.
|
||||||
|
while (hasKind(ifStatement.parent, SyntaxKind.IfStatement) && (<IfStatement>ifStatement.parent).elseStatement === ifStatement) {
|
||||||
|
ifStatement = <IfStatement>ifStatement.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now traverse back down through the else branches, aggregating if/else keywords of if-statements.
|
||||||
|
while (ifStatement) {
|
||||||
|
let children = ifStatement.getChildren();
|
||||||
|
pushKeywordIf(keywords, children[0], SyntaxKind.IfKeyword);
|
||||||
|
|
||||||
|
// Generally the 'else' keyword is second-to-last, so we traverse backwards.
|
||||||
|
for (let i = children.length - 1; i >= 0; i--) {
|
||||||
|
if (pushKeywordIf(keywords, children[i], SyntaxKind.ElseKeyword)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasKind(ifStatement.elseStatement, SyntaxKind.IfStatement)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
ifStatement = <IfStatement>ifStatement.elseStatement;
|
||||||
|
}
|
||||||
|
|
||||||
|
let result: HighlightSpan[] = [];
|
||||||
|
|
||||||
|
// We'd like to highlight else/ifs together if they are only separated by whitespace
|
||||||
|
// (i.e. the keywords are separated by no comments, no newlines).
|
||||||
|
for (let i = 0; i < keywords.length; i++) {
|
||||||
|
if (keywords[i].kind === SyntaxKind.ElseKeyword && i < keywords.length - 1) {
|
||||||
|
let elseKeyword = keywords[i];
|
||||||
|
let ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword.
|
||||||
|
|
||||||
|
let shouldCombindElseAndIf = true;
|
||||||
|
|
||||||
|
// Avoid recalculating getStart() by iterating backwards.
|
||||||
|
for (let j = ifKeyword.getStart() - 1; j >= elseKeyword.end; j--) {
|
||||||
|
if (!isWhiteSpace(sourceFile.text.charCodeAt(j))) {
|
||||||
|
shouldCombindElseAndIf = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldCombindElseAndIf) {
|
||||||
|
result.push({
|
||||||
|
fileName: fileName,
|
||||||
|
textSpan: createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end),
|
||||||
|
kind: DocumentHighlightKind.reference
|
||||||
|
});
|
||||||
|
i++; // skip the next keyword
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ordinary case: just highlight the keyword.
|
||||||
|
result.push(getHighlightSpanForNode(keywords[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// References and Occurrences
|
||||||
|
function getOccurrencesAtPositionCore(fileName: string, position: number): ReferenceEntry[] {
|
||||||
|
synchronizeHostData();
|
||||||
|
|
||||||
|
return convertDocumentHighlights(getDocumentHighlights(fileName, position, [fileName]));
|
||||||
|
|
||||||
|
function convertDocumentHighlights(documentHighlights: DocumentHighlights[]): ReferenceEntry[] {
|
||||||
|
if (!documentHighlights) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
let result: ReferenceEntry[] = [];
|
||||||
|
for (let entry of documentHighlights) {
|
||||||
|
for (let highlightSpan of entry.highlightSpans) {
|
||||||
|
result.push({
|
||||||
|
fileName: entry.fileName,
|
||||||
|
textSpan: highlightSpan.textSpan,
|
||||||
|
isWriteAccess: highlightSpan.kind === DocumentHighlightKind.writtenReference
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertReferences(referenceSymbols: ReferencedSymbol[]): ReferenceEntry[] {
|
function convertReferences(referenceSymbols: ReferencedSymbol[]): ReferenceEntry[] {
|
||||||
|
@ -4518,9 +4628,11 @@ module ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
let referenceEntries: ReferenceEntry[] = [];
|
let referenceEntries: ReferenceEntry[] = [];
|
||||||
|
|
||||||
for (let referenceSymbol of referenceSymbols) {
|
for (let referenceSymbol of referenceSymbols) {
|
||||||
addRange(referenceEntries, referenceSymbol.references);
|
addRange(referenceEntries, referenceSymbol.references);
|
||||||
}
|
}
|
||||||
|
|
||||||
return referenceEntries;
|
return referenceEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4561,10 +4673,10 @@ module ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.assert(node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.NumericLiteral || node.kind === SyntaxKind.StringLiteral);
|
Debug.assert(node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.NumericLiteral || node.kind === SyntaxKind.StringLiteral);
|
||||||
return getReferencesForNode(node, program.getSourceFiles(), /*searchOnlyInCurrentFile*/ false, findInStrings, findInComments);
|
return getReferencedSymbolsForNodes(node, program.getSourceFiles(), findInStrings, findInComments);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getReferencesForNode(node: Node, sourceFiles: SourceFile[], searchOnlyInCurrentFile: boolean, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[]{
|
function getReferencedSymbolsForNodes(node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean): ReferencedSymbol[]{
|
||||||
// Labels
|
// Labels
|
||||||
if (isLabelName(node)) {
|
if (isLabelName(node)) {
|
||||||
if (isJumpStatementTarget(node)) {
|
if (isJumpStatementTarget(node)) {
|
||||||
|
@ -4621,15 +4733,9 @@ module ts {
|
||||||
result = [];
|
result = [];
|
||||||
getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
|
getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (searchOnlyInCurrentFile) {
|
|
||||||
Debug.assert(sourceFiles.length === 1);
|
|
||||||
result = [];
|
|
||||||
getReferencesInNode(sourceFiles[0], symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
let internedName = getInternedName(symbol, node, declarations)
|
let internedName = getInternedName(symbol, node, declarations)
|
||||||
forEach(sourceFiles, sourceFile => {
|
for (let sourceFile of sourceFiles) {
|
||||||
cancellationToken.throwIfCancellationRequested();
|
cancellationToken.throwIfCancellationRequested();
|
||||||
|
|
||||||
let nameTable = getNameTable(sourceFile);
|
let nameTable = getNameTable(sourceFile);
|
||||||
|
@ -4638,7 +4744,6 @@ module ts {
|
||||||
result = result || [];
|
result = result || [];
|
||||||
getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
|
getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6255,6 +6360,7 @@ module ts {
|
||||||
getReferencesAtPosition,
|
getReferencesAtPosition,
|
||||||
findReferences,
|
findReferences,
|
||||||
getOccurrencesAtPosition,
|
getOccurrencesAtPosition,
|
||||||
|
getDocumentHighlights,
|
||||||
getNameOrDottedNameSpan,
|
getNameOrDottedNameSpan,
|
||||||
getBreakpointStatementAtPosition,
|
getBreakpointStatementAtPosition,
|
||||||
getNavigateToItems,
|
getNavigateToItems,
|
||||||
|
|
|
@ -135,11 +135,21 @@ module ts {
|
||||||
findReferences(fileName: string, position: number): string;
|
findReferences(fileName: string, position: number): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @deprecated
|
||||||
* Returns a JSON-encoded value of the type:
|
* Returns a JSON-encoded value of the type:
|
||||||
* { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
|
* { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
|
||||||
*/
|
*/
|
||||||
getOccurrencesAtPosition(fileName: string, position: number): string;
|
getOccurrencesAtPosition(fileName: string, position: number): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a JSON-encoded value of the type:
|
||||||
|
* { fileName: string; highlights: { start: number; length: number, isDefinition: boolean }[] }[]
|
||||||
|
*
|
||||||
|
* @param fileToSearch A JSON encoded string[] containing the file names that should be
|
||||||
|
* considered when searching.
|
||||||
|
*/
|
||||||
|
getDocumentHighlights(fileName: string, position: number, filesToSearch: string): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a JSON-encoded value of the type:
|
* Returns a JSON-encoded value of the type:
|
||||||
* { name: string; kind: string; kindModifiers: string; containerName: string; containerKind: string; matchKind: string; fileName: string; textSpan: { start: number; length: number}; } [] = [];
|
* { name: string; kind: string; kindModifiers: string; containerName: string; containerKind: string; matchKind: string; fileName: string; textSpan: { start: number; length: number}; } [] = [];
|
||||||
|
@ -590,6 +600,14 @@ module ts {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getDocumentHighlights(fileName: string, position: number, filesToSearch: string): string {
|
||||||
|
return this.forwardJSONCall(
|
||||||
|
"getDocumentHighlights('" + fileName + "', " + position + ")",
|
||||||
|
() => {
|
||||||
|
return this.languageService.getDocumentHighlights(fileName, position, JSON.parse(filesToSearch));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// COMPLETION LISTS
|
/// COMPLETION LISTS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue