refactor(language-service): do not mutate the original template node span (#40484)

Rather than mutating the span on the template when renaming literal strings,
this commit updates the logic to mutate the `TextSpan` equivalent that
is used by the Language Service.

PR Close #40484
This commit is contained in:
Andrew Scott 2021-01-19 08:40:00 -08:00 committed by Jessica Janiuk
parent 3cf4e3c7c5
commit 5bbb5ea955
2 changed files with 18 additions and 10 deletions

View File

@ -87,7 +87,7 @@ export class ReferencesAndRenameBuilder {
canRename: true, canRename: true,
displayName: text, displayName: text,
fullDisplayName: text, fullDisplayName: text,
triggerSpan: toTextSpan(span), triggerSpan: span,
}; };
} }
@ -396,19 +396,19 @@ export class ReferencesAndRenameBuilder {
} }
} }
function getRenameTextAndSpanAtPosition(node: TmplAstNode|AST, position: number): function getRenameTextAndSpanAtPosition(
{text: string, span: ParseSourceSpan|AbsoluteSourceSpan}|null { node: TmplAstNode|AST, position: number): {text: string, span: ts.TextSpan}|null {
if (node instanceof TmplAstBoundAttribute || node instanceof TmplAstTextAttribute || if (node instanceof TmplAstBoundAttribute || node instanceof TmplAstTextAttribute ||
node instanceof TmplAstBoundEvent) { node instanceof TmplAstBoundEvent) {
if (node.keySpan === undefined) { if (node.keySpan === undefined) {
return null; return null;
} }
return {text: node.name, span: node.keySpan}; return {text: node.name, span: toTextSpan(node.keySpan)};
} else if (node instanceof TmplAstVariable || node instanceof TmplAstReference) { } else if (node instanceof TmplAstVariable || node instanceof TmplAstReference) {
if (isWithin(position, node.keySpan)) { if (isWithin(position, node.keySpan)) {
return {text: node.keySpan.toString(), span: node.keySpan}; return {text: node.keySpan.toString(), span: toTextSpan(node.keySpan)};
} else if (node.valueSpan && isWithin(position, node.valueSpan)) { } else if (node.valueSpan && isWithin(position, node.valueSpan)) {
return {text: node.valueSpan.toString(), span: node.valueSpan}; return {text: node.valueSpan.toString(), span: toTextSpan(node.valueSpan)};
} }
} }
@ -418,14 +418,14 @@ function getRenameTextAndSpanAtPosition(node: TmplAstNode|AST, position: number)
} }
if (node instanceof PropertyRead || node instanceof MethodCall || node instanceof PropertyWrite || if (node instanceof PropertyRead || node instanceof MethodCall || node instanceof PropertyWrite ||
node instanceof SafePropertyRead || node instanceof SafeMethodCall) { node instanceof SafePropertyRead || node instanceof SafeMethodCall) {
return {text: node.name, span: node.nameSpan}; return {text: node.name, span: toTextSpan(node.nameSpan)};
} else if (node instanceof LiteralPrimitive) { } else if (node instanceof LiteralPrimitive) {
const span = node.span; const span = toTextSpan(node.sourceSpan);
const text = node.value; const text = node.value;
if (typeof text === 'string') { if (typeof text === 'string') {
// The span of a string literal includes the quotes but they should be removed for renaming. // The span of a string literal includes the quotes but they should be removed for renaming.
span.start += 1; span.start += 1;
span.end -= 1; span.length -= 2;
} }
return {text, span}; return {text, span};
} }

View File

@ -1425,7 +1425,15 @@ describe('find references and rename locations', () => {
expect(result.canRename).toEqual(true); expect(result.canRename).toEqual(true);
expect(result.displayName).toEqual('myProp'); expect(result.displayName).toEqual('myProp');
expect(result.kind).toEqual('property'); expect(result.kind).toEqual('property');
expect(result.triggerSpan.length).toEqual('myProp'.length); expect(text.substring(
result.triggerSpan.start, result.triggerSpan.start + result.triggerSpan.length))
.toBe('myProp');
// re-queries also work
const {triggerSpan, displayName} =
env.ngLS.getRenameInfo(_('/my-comp.ts'), cursor) as ts.RenameInfoSuccess;
expect(displayName).toEqual('myProp');
expect(text.substring(triggerSpan.start, triggerSpan.start + triggerSpan.length))
.toBe('myProp');
}); });
it('gets rename info when cursor is on a directive input in a template', () => { it('gets rename info when cursor is on a directive input in a template', () => {