mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-08 02:46:15 -05:00
Combine getTouchingWord and getTouchingPropertyName (#22127)
This commit is contained in:
@@ -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));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* @internal */
|
||||
namespace ts.DocumentHighlights {
|
||||
export function getDocumentHighlights(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: ReadonlyArray<SourceFile>): 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.
|
||||
|
||||
@@ -716,6 +716,10 @@ namespace ts.FindAllReferences.Core {
|
||||
});
|
||||
}
|
||||
|
||||
function getPossibleSymbolReferenceNodes(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile): ReadonlyArray<Node> {
|
||||
return getPossibleSymbolReferencePositions(sourceFile, symbolName, container).map(pos => getTouchingPropertyName(sourceFile, pos, /*includeJsDocComment*/ true));
|
||||
}
|
||||
|
||||
function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile): ReadonlyArray<number> {
|
||||
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<SourceFile>, 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(<SourceFile>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<number>, staticFlag: ModifierFlags, result: Push<Entry>): 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(<SourceFile>container)) {
|
||||
result.push(nodeEntry(node));
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getReferencesForStringLiteral(node: StringLiteral, sourceFiles: ReadonlyArray<SourceFile>, 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 [{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user