Skip to content

Commit 2a8b9ef

Browse files
Support rename in comments and strings.
1 parent 00e5b15 commit 2a8b9ef

6 files changed

Lines changed: 121 additions & 12 deletions

File tree

src/compiler/checker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2575,7 +2575,7 @@ module ts {
25752575
function getStringLiteralType(node: StringLiteralTypeNode): StringLiteralType {
25762576
if (hasProperty(stringLiteralTypes, node.text)) return stringLiteralTypes[node.text];
25772577
var type = stringLiteralTypes[node.text] = <StringLiteralType>createType(TypeFlags.StringLiteral);
2578-
type.text = getSourceTextOfNode(node);
2578+
type.text = getTextOfNode(node);
25792579
return type;
25802580
}
25812581

@@ -7430,7 +7430,7 @@ module ts {
74307430
while (!isUniqueLocalName(escapeIdentifier(prefix + name), container)) {
74317431
prefix += "_";
74327432
}
7433-
links.localModuleName = prefix + getSourceTextOfNode(container.name);
7433+
links.localModuleName = prefix + getTextOfNode(container.name);
74347434
}
74357435
return links.localModuleName;
74367436
}

src/compiler/parser.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ module ts {
5454
return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos);
5555
}
5656

57-
export function getSourceTextOfNodeFromSourceText(sourceText: string, node: Node): string {
57+
export function getTextOfNodeFromSourceText(sourceText: string, node: Node): string {
5858
return sourceText.substring(skipTrivia(sourceText, node.pos), node.end);
5959
}
6060

61-
export function getSourceTextOfNode(node: Node): string {
61+
export function getTextOfNode(node: Node): string {
6262
var text = getSourceFileOfNode(node).text;
6363
return text.substring(skipTrivia(text, node.pos), node.end);
6464
}
@@ -75,7 +75,7 @@ module ts {
7575

7676
// Return display name of an identifier
7777
export function identifierToString(identifier: Identifier) {
78-
return identifier.kind === SyntaxKind.Missing ? "(Missing)" : getSourceTextOfNode(identifier);
78+
return identifier.kind === SyntaxKind.Missing ? "(Missing)" : getTextOfNode(identifier);
7979
}
8080

8181
export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic {
@@ -3045,7 +3045,7 @@ module ts {
30453045
parseExpected(SyntaxKind.ColonToken);
30463046

30473047
if (labelledStatementInfo.nodeIsNestedInLabel(node.label, /*requireIterationStatement*/ false, /*stopAtFunctionBoundary*/ true)) {
3048-
grammarErrorOnNode(node.label, Diagnostics.Duplicate_label_0, getSourceTextOfNodeFromSourceText(sourceText, node.label));
3048+
grammarErrorOnNode(node.label, Diagnostics.Duplicate_label_0, getTextOfNodeFromSourceText(sourceText, node.label));
30493049
}
30503050
labelledStatementInfo.addLabel(node.label);
30513051

src/harness/typeWriter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class TypeWriterWalker {
7676
private log(node: ts.Node, type: ts.Type): void {
7777
var actualPos = ts.skipTrivia(this.currentSourceFile.text, node.pos);
7878
var lineAndCharacter = this.currentSourceFile.getLineAndCharacterFromPosition(actualPos);
79-
var sourceText = ts.getSourceTextOfNodeFromSourceText(this.currentSourceFile.text, node);
79+
var sourceText = ts.getTextOfNodeFromSourceText(this.currentSourceFile.text, node);
8080

8181
// If we got an unknown type, we temporarily want to fall back to just pretending the name
8282
// (source text) of the node is the type. This is to align with the old typeWriter to make

src/services/services.ts

Lines changed: 99 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,8 @@ module ts {
666666
getSignatureAtPosition(fileName: string, position: number): SignatureInfo;
667667

668668
getRenameInfo(fileName: string, position: number): RenameInfo;
669+
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[];
670+
669671
getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
670672
getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[];
671673
getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[];
@@ -757,6 +759,11 @@ module ts {
757759
newText: string;
758760
}
759761

762+
export interface RenameLocation {
763+
textSpan: TypeScript.TextSpan;
764+
fileName: string;
765+
}
766+
760767
export interface ReferenceEntry {
761768
textSpan: TypeScript.TextSpan;
762769
fileName: string;
@@ -3062,11 +3069,19 @@ module ts {
30623069
}
30633070
}
30643071

3065-
function getReferencesAtPosition(filename: string, position: number): ReferenceEntry[] {
3072+
function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] {
3073+
return findReferences(fileName, position, findInStrings, findInComments);
3074+
}
3075+
3076+
function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] {
3077+
return findReferences(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false);
3078+
}
3079+
3080+
function findReferences(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReferenceEntry[] {
30663081
synchronizeHostData();
30673082

3068-
filename = TypeScript.switchToForwardSlashes(filename);
3069-
var sourceFile = getSourceFile(filename);
3083+
fileName = TypeScript.switchToForwardSlashes(fileName);
3084+
var sourceFile = getSourceFile(fileName);
30703085

30713086
var node = getTouchingPropertyName(sourceFile, position);
30723087
if (!node) {
@@ -3082,7 +3097,86 @@ module ts {
30823097
return undefined;
30833098
}
30843099

3085-
return getReferencesForNode(node, program.getSourceFiles());
3100+
Debug.assert(node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.NumericLiteral || node.kind === SyntaxKind.StringLiteral);
3101+
var references = getReferencesForNode(node, program.getSourceFiles());
3102+
3103+
var name = (<Identifier>node).text;
3104+
var tripleSlashDirectivePrefixRegex = /^\/\/\/\s*</
3105+
3106+
if (findInStrings) {
3107+
forEach(program.getSourceFiles(), addStringReferences);
3108+
}
3109+
3110+
if (findInComments) {
3111+
forEach(program.getSourceFiles(), addCommentReferences);
3112+
}
3113+
3114+
return references;
3115+
3116+
function addReferencesInRawText(rawText: string, rawTextPositionInSourceText: number, sourceText: string) {
3117+
var matchIndex = 0;
3118+
while ((matchIndex = rawText.indexOf(name, matchIndex)) >= 0) {
3119+
// Only consider it a match if there isn't a letter/number before or after
3120+
// the match.
3121+
var indexInSourceText = rawTextPositionInSourceText + matchIndex;
3122+
3123+
if (indexInSourceText === 0 || !isIdentifierPart(sourceText.charCodeAt(indexInSourceText - 1), ScriptTarget.ES5)) {
3124+
var matchEnd = indexInSourceText + name.length;
3125+
if (matchEnd >= sourceText.length || !isIdentifierPart(sourceText.charCodeAt(matchEnd), ScriptTarget.ES5)) {
3126+
3127+
references.push({
3128+
fileName: sourceFile.filename,
3129+
textSpan: new TypeScript.TextSpan(indexInSourceText, name.length),
3130+
isWriteAccess: false
3131+
});
3132+
}
3133+
}
3134+
3135+
matchIndex++;
3136+
}
3137+
}
3138+
3139+
function addCommentReferences(sourceFile: SourceFile) {
3140+
var sourceText = sourceFile.text;
3141+
forEachChild(sourceFile, addCommentReferencesInNode);
3142+
3143+
function addCommentReferencesInNode(node: Node) {
3144+
if (isToken(node)) {
3145+
// Found a token, walk its comments (if it has any) for matches).
3146+
forEach(getLeadingCommentRanges(sourceText, node.pos), addReferencesInCommentRange);
3147+
}
3148+
else {
3149+
forEach(node.getChildren(), addCommentReferencesInNode);
3150+
}
3151+
}
3152+
3153+
function addReferencesInCommentRange(range: CommentRange) {
3154+
var commentText = sourceText.substring(range.pos, range.end);
3155+
3156+
// Don't add matches in ///<reference comments. We don't want to
3157+
// unintentionally update a file name.
3158+
if (!tripleSlashDirectivePrefixRegex.test(commentText)) {
3159+
addReferencesInRawText(commentText, range.pos, sourceText);
3160+
}
3161+
}
3162+
}
3163+
3164+
function addStringReferences(sourceFile: SourceFile) {
3165+
var sourceText = sourceFile.text;
3166+
3167+
forEachChild(sourceFile, addStringReferencesInNode);
3168+
3169+
function addStringReferencesInNode(node: Node) {
3170+
if (node.kind === SyntaxKind.StringLiteral) {
3171+
// Found a string literal. See if we can find any matches in it.
3172+
addReferencesInRawText(getTextOfNodeFromSourceText(sourceText, node), node.getStart(sourceFile), sourceText);
3173+
}
3174+
else {
3175+
// Recurse and keep looking for references in strings.
3176+
forEachChild(node, addStringReferencesInNode);
3177+
}
3178+
}
3179+
}
30863180
}
30873181

30883182
function getReferencesForNode(node: Node, sourceFiles: SourceFile[]): ReferenceEntry[] {
@@ -4590,6 +4684,7 @@ module ts {
45904684
getBreakpointStatementAtPosition: getBreakpointStatementAtPosition,
45914685
getNavigateToItems: getNavigateToItems,
45924686
getRenameInfo: getRenameInfo,
4687+
findRenameLocations: findRenameLocations,
45934688
getNavigationBarItems: getNavigationBarItems,
45944689
getOutliningSpans: getOutliningSpans,
45954690
getTodoComments: getTodoComments,

src/services/shims.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ module ts {
102102
*/
103103
getRenameInfo(fileName: string, position: number): string;
104104

105+
/**
106+
* Returns a JSON-encoded value of the type:
107+
* { fileName: string, textSpan: { start: number, length: number } }[]
108+
*/
109+
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): string;
110+
105111
/**
106112
* Returns a JSON-encoded value of the type:
107113
* { fileName: string; textSpan: { start: number; length: number}; kind: string; name: string; containerKind: string; containerName: string }
@@ -650,6 +656,14 @@ module ts {
650656
});
651657
}
652658

659+
public findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): string {
660+
return this.forwardJSONCall(
661+
"findRenameLocations('" + fileName + "', " + position + ", " + findInStrings + ", " + findInComments + ")",
662+
() => {
663+
return this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments);
664+
});
665+
}
666+
653667
/// GET BRACE MATCHING
654668
public getBraceMatchingAtPosition(fileName: string, position: number): string {
655669
return this.forwardJSONCall(

src/services/utilities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ module ts {
222222
return n.kind !== SyntaxKind.SyntaxList || n.getChildCount() !== 0;
223223
}
224224

225-
function isToken(n: Node): boolean {
225+
export function isToken(n: Node): boolean {
226226
return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken;
227227
}
228228

0 commit comments

Comments
 (0)