From abbb79f972f55a952aa66caedbf58eb26f0fcea3 Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 12 Apr 2018 11:56:40 -0700 Subject: [PATCH] Combine getTouchingWord and getTouchingPropertyName (#22127) --- src/services/completions.ts | 2 +- src/services/documentHighlights.ts | 2 +- src/services/findAllReferences.ts | 94 +++++++++++------------------- src/services/organizeImports.ts | 4 +- src/services/rename.ts | 2 +- src/services/utilities.ts | 22 ++----- 6 files changed, 43 insertions(+), 83 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 6e77d71840e..bfae5ada0db 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -844,7 +844,7 @@ namespace ts.Completions { // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS| // Skip this partial identifier and adjust the contextToken to the token that precedes it. - if (contextToken && position <= contextToken.end && isWord(contextToken.kind)) { + if (contextToken && position <= contextToken.end && (isIdentifier(contextToken) || isKeyword(contextToken.kind))) { const start = timestamp(); contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression); log("getCompletionData: Get previous token 2: " + (timestamp() - start)); diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index b89c722a275..69c75548fe5 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -1,7 +1,7 @@ /* @internal */ namespace ts.DocumentHighlights { export function getDocumentHighlights(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: ReadonlyArray): DocumentHighlights[] | undefined { - const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true); + const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true); if (node.parent && (isJsxOpeningElement(node.parent) && node.parent.tagName === node || isJsxClosingElement(node.parent))) { // For a JSX element, just highlight the matching tag, not all references. diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 80ed225575b..7d6d78af163 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -716,6 +716,10 @@ namespace ts.FindAllReferences.Core { }); } + function getPossibleSymbolReferenceNodes(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile): ReadonlyArray { + return getPossibleSymbolReferencePositions(sourceFile, symbolName, container).map(pos => getTouchingPropertyName(sourceFile, pos, /*includeJsDocComment*/ true)); + } + function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile): ReadonlyArray { const positions: number[] = []; @@ -754,11 +758,9 @@ namespace ts.FindAllReferences.Core { function getLabelReferencesInNode(container: Node, targetLabel: Identifier): SymbolAndEntries[] { const sourceFile = container.getSourceFile(); const labelName = targetLabel.text; - const references = mapDefined(getPossibleSymbolReferencePositions(sourceFile, labelName, container), position => { - const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ false); + const references = mapDefined(getPossibleSymbolReferenceNodes(sourceFile, labelName, container), node => // Only pick labels that are either the target label, or have a target that is the target label - return node && (node === targetLabel || (isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel)) ? nodeEntry(node) : undefined; - }); + node === targetLabel || (isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel) ? nodeEntry(node) : undefined); return [{ definition: { type: "label", node: targetLabel }, references }]; } @@ -788,10 +790,8 @@ namespace ts.FindAllReferences.Core { function getAllReferencesForKeyword(sourceFiles: ReadonlyArray, keywordKind: SyntaxKind, cancellationToken: CancellationToken): SymbolAndEntries[] { const references = flatMap(sourceFiles, sourceFile => { cancellationToken.throwIfCancellationRequested(); - return mapDefined(getPossibleSymbolReferencePositions(sourceFile, tokenToString(keywordKind), sourceFile), position => { - const referenceLocation = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true); - return referenceLocation.kind === keywordKind ? nodeEntry(referenceLocation) : undefined; - }); + return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, tokenToString(keywordKind), sourceFile), referenceLocation => + referenceLocation.kind === keywordKind ? nodeEntry(referenceLocation) : undefined); }); return references.length ? [{ definition: { type: "keyword", node: references[0].node }, references }] : undefined; } @@ -1255,9 +1255,8 @@ namespace ts.FindAllReferences.Core { } const sourceFile = searchSpaceNode.getSourceFile(); - const references = mapDefined(getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode), position => { - const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ false); - if (!node || node.kind !== SyntaxKind.SuperKeyword) { + const references = mapDefined(getPossibleSymbolReferenceNodes(sourceFile, "super", searchSpaceNode), node => { + if (node.kind !== SyntaxKind.SuperKeyword) { return; } @@ -1307,12 +1306,30 @@ namespace ts.FindAllReferences.Core { return undefined; } - const references: Entry[] = []; - for (const sourceFile of searchSpaceNode.kind === SyntaxKind.SourceFile ? sourceFiles : [searchSpaceNode.getSourceFile()]) { + const references = flatMap(searchSpaceNode.kind === SyntaxKind.SourceFile ? sourceFiles : [searchSpaceNode.getSourceFile()], sourceFile => { cancellationToken.throwIfCancellationRequested(); - const positions = getPossibleSymbolReferencePositions(sourceFile, "this", isSourceFile(searchSpaceNode) ? sourceFile : searchSpaceNode); - getThisReferencesInFile(sourceFile, searchSpaceNode.kind === SyntaxKind.SourceFile ? sourceFile : searchSpaceNode, positions, staticFlag, references); - } + return getPossibleSymbolReferenceNodes(sourceFile, "this", isSourceFile(searchSpaceNode) ? sourceFile : searchSpaceNode).filter(node => { + if (!isThis(node)) { + return false; + } + const container = getThisContainer(node, /* includeArrowFunctions */ false); + switch (searchSpaceNode.kind) { + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + return searchSpaceNode.symbol === container.symbol; + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + return isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol; + case SyntaxKind.ClassExpression: + case SyntaxKind.ClassDeclaration: + // Make sure the container belongs to the same class + // and has the appropriate static modifier from the original container. + return container.parent && searchSpaceNode.symbol === container.parent.symbol && (getModifierFlags(container) & ModifierFlags.Static) === staticFlag; + case SyntaxKind.SourceFile: + return container.kind === SyntaxKind.SourceFile && !isExternalModule(container); + } + }); + }).map(n => nodeEntry(n)); return [{ definition: { type: "this", node: thisOrSuperKeyword }, @@ -1320,52 +1337,11 @@ namespace ts.FindAllReferences.Core { }]; } - function getThisReferencesInFile(sourceFile: SourceFile, searchSpaceNode: Node, possiblePositions: ReadonlyArray, staticFlag: ModifierFlags, result: Push): void { - forEach(possiblePositions, position => { - const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ false); - if (!node || !isThis(node)) { - return; - } - - const container = getThisContainer(node, /* includeArrowFunctions */ false); - - switch (searchSpaceNode.kind) { - case SyntaxKind.FunctionExpression: - case SyntaxKind.FunctionDeclaration: - if (searchSpaceNode.symbol === container.symbol) { - result.push(nodeEntry(node)); - } - break; - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - if (isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol) { - result.push(nodeEntry(node)); - } - break; - case SyntaxKind.ClassExpression: - case SyntaxKind.ClassDeclaration: - // Make sure the container belongs to the same class - // and has the appropriate static modifier from the original container. - if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (getModifierFlags(container) & ModifierFlags.Static) === staticFlag) { - result.push(nodeEntry(node)); - } - break; - case SyntaxKind.SourceFile: - if (container.kind === SyntaxKind.SourceFile && !isExternalModule(container)) { - result.push(nodeEntry(node)); - } - break; - } - }); - } - function getReferencesForStringLiteral(node: StringLiteral, sourceFiles: ReadonlyArray, cancellationToken: CancellationToken): SymbolAndEntries[] { const references = flatMap(sourceFiles, sourceFile => { cancellationToken.throwIfCancellationRequested(); - return mapDefined(getPossibleSymbolReferencePositions(sourceFile, node.text), position => { - const ref = tryCast(getTouchingWord(sourceFile, position, /*includeJsDocComment*/ false), isStringLiteral); - return ref && ref.text === node.text ? nodeEntry(ref, /*isInString*/ true) : undefined; - }); + return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, node.text), ref => + isStringLiteral(ref) && ref.text === node.text ? nodeEntry(ref, /*isInString*/ true) : undefined); }); return [{ diff --git a/src/services/organizeImports.ts b/src/services/organizeImports.ts index 52f9a50366f..5109b050b6b 100644 --- a/src/services/organizeImports.ts +++ b/src/services/organizeImports.ts @@ -131,9 +131,7 @@ namespace ts.OrganizeImports { } function getExternalModuleName(specifier: Expression) { - return isStringLiteral(specifier) || isNoSubstitutionTemplateLiteral(specifier) - ? specifier.text - : undefined; + return isStringLiteralLike(specifier) ? specifier.text : undefined; } /* @internal */ // Internal for testing diff --git a/src/services/rename.ts b/src/services/rename.ts index c40f7908776..2f9de0c0cad 100644 --- a/src/services/rename.ts +++ b/src/services/rename.ts @@ -2,7 +2,7 @@ namespace ts.Rename { export function getRenameInfo(typeChecker: TypeChecker, defaultLibFileName: string, getCanonicalFileName: GetCanonicalFileName, sourceFile: SourceFile, position: number): RenameInfo { const getCanonicalDefaultLibName = memoize(() => getCanonicalFileName(normalizePath(defaultLibFileName))); - const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true); + const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true); const renameInfo = node && nodeIsEligibleForRename(node) ? getRenameInfoForNode(node, typeChecker, sourceFile, isDefinedInLibraryFile) : undefined; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index ce9c02b736e..63170678202 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -627,18 +627,12 @@ namespace ts { return syntaxList; } - /* Gets the token whose text has range [start, end) and - * position >= start and (position < end or (position === end && token is keyword or identifier)) - */ - export function getTouchingWord(sourceFile: SourceFile, position: number, includeJsDocComment: boolean): Node { - return getTouchingToken(sourceFile, position, includeJsDocComment, n => isWord(n.kind)); - } - - /* Gets the token whose text has range [start, end) and position >= start - * and (position < end or (position === end && token is keyword or identifier or numeric/string literal)) + /** + * Gets the token whose text has range [start, end) and + * position >= start and (position < end or (position === end && token is literal or keyword or identifier)) */ export function getTouchingPropertyName(sourceFile: SourceFile, position: number, includeJsDocComment: boolean): Node { - return getTouchingToken(sourceFile, position, includeJsDocComment, n => isPropertyName(n.kind)); + return getTouchingToken(sourceFile, position, includeJsDocComment, n => isPropertyNameLiteral(n) || isKeyword(n.kind)); } /** @@ -1059,14 +1053,6 @@ namespace ts { return undefined; } - export function isWord(kind: SyntaxKind): boolean { - return kind === SyntaxKind.Identifier || isKeyword(kind); - } - - function isPropertyName(kind: SyntaxKind): boolean { - return kind === SyntaxKind.StringLiteral || kind === SyntaxKind.NumericLiteral || isWord(kind); - } - export function isComment(kind: SyntaxKind): boolean { return kind === SyntaxKind.SingleLineCommentTrivia || kind === SyntaxKind.MultiLineCommentTrivia; }