refactor(language-service): Separate reference and rename capabilities (#40523)
This commit separates the reference and rename functions into separate builders so it's easier to locate functions specific to each PR Close #40523
This commit is contained in:
parent
9bc8b343ea
commit
c1bcbeb324
|
@ -26,7 +26,7 @@ import {CompilerFactory} from './compiler_factory';
|
|||
import {CompletionBuilder, CompletionNodeContext} from './completions';
|
||||
import {DefinitionBuilder} from './definitions';
|
||||
import {QuickInfoBuilder} from './quick_info';
|
||||
import {ReferencesAndRenameBuilder} from './references_and_rename';
|
||||
import {ReferencesBuilder, RenameBuilder} from './references_and_rename';
|
||||
import {getSignatureHelp} from './signature_help';
|
||||
import {getTargetAtPosition, TargetContext, TargetNodeKind} from './template_target';
|
||||
import {findTightestNode, getClassDeclFromDecoratorProp, getPropertyAssignmentFromValue} from './ts_utils';
|
||||
|
@ -168,14 +168,14 @@ export class LanguageService {
|
|||
|
||||
getReferencesAtPosition(fileName: string, position: number): ts.ReferenceEntry[]|undefined {
|
||||
return this.withCompilerAndPerfTracing(PerfPhase.LsReferencesAndRenames, (compiler) => {
|
||||
return new ReferencesAndRenameBuilder(this.programDriver, this.tsLS, compiler)
|
||||
return new ReferencesBuilder(this.programDriver, this.tsLS, compiler)
|
||||
.getReferencesAtPosition(fileName, position);
|
||||
});
|
||||
}
|
||||
|
||||
getRenameInfo(fileName: string, position: number): ts.RenameInfo {
|
||||
return this.withCompilerAndPerfTracing(PerfPhase.LsReferencesAndRenames, (compiler) => {
|
||||
const renameInfo = new ReferencesAndRenameBuilder(this.programDriver, this.tsLS, compiler)
|
||||
const renameInfo = new RenameBuilder(this.programDriver, this.tsLS, compiler)
|
||||
.getRenameInfo(absoluteFrom(fileName), position);
|
||||
if (!renameInfo.canRename) {
|
||||
return renameInfo;
|
||||
|
@ -191,7 +191,7 @@ export class LanguageService {
|
|||
|
||||
findRenameLocations(fileName: string, position: number): readonly ts.RenameLocation[]|undefined {
|
||||
return this.withCompilerAndPerfTracing(PerfPhase.LsReferencesAndRenames, (compiler) => {
|
||||
return new ReferencesAndRenameBuilder(this.programDriver, this.tsLS, compiler)
|
||||
return new RenameBuilder(this.programDriver, this.tsLS, compiler)
|
||||
.findRenameLocations(fileName, position);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -16,6 +16,61 @@ import {convertToTemplateDocumentSpan, createLocationKey, getRenameTextAndSpanAt
|
|||
import {findTightestNode} from './ts_utils';
|
||||
import {getTemplateInfoAtPosition, TemplateInfo} from './utils';
|
||||
|
||||
export class ReferencesBuilder {
|
||||
private readonly ttc = this.compiler.getTemplateTypeChecker();
|
||||
|
||||
constructor(
|
||||
private readonly driver: ProgramDriver, private readonly tsLS: ts.LanguageService,
|
||||
private readonly compiler: NgCompiler) {}
|
||||
|
||||
getReferencesAtPosition(filePath: string, position: number): ts.ReferenceEntry[]|undefined {
|
||||
this.ttc.generateAllTypeCheckBlocks();
|
||||
const templateInfo = getTemplateInfoAtPosition(filePath, position, this.compiler);
|
||||
if (templateInfo === undefined) {
|
||||
return this.getReferencesAtTypescriptPosition(filePath, position);
|
||||
}
|
||||
return this.getReferencesAtTemplatePosition(templateInfo, position);
|
||||
}
|
||||
|
||||
private getReferencesAtTemplatePosition(templateInfo: TemplateInfo, position: number):
|
||||
ts.ReferenceEntry[]|undefined {
|
||||
const allTargetDetails = getTargetDetailsAtTemplatePosition(templateInfo, position, this.ttc);
|
||||
if (allTargetDetails === null) {
|
||||
return undefined;
|
||||
}
|
||||
const allReferences: ts.ReferenceEntry[] = [];
|
||||
for (const targetDetails of allTargetDetails) {
|
||||
for (const location of targetDetails.typescriptLocations) {
|
||||
const refs = this.getReferencesAtTypescriptPosition(location.fileName, location.position);
|
||||
if (refs !== undefined) {
|
||||
allReferences.push(...refs);
|
||||
}
|
||||
}
|
||||
}
|
||||
return allReferences.length > 0 ? allReferences : undefined;
|
||||
}
|
||||
|
||||
private getReferencesAtTypescriptPosition(fileName: string, position: number):
|
||||
ts.ReferenceEntry[]|undefined {
|
||||
const refs = this.tsLS.getReferencesAtPosition(fileName, position);
|
||||
if (refs === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const entries: Map<string, ts.ReferenceEntry> = new Map();
|
||||
for (const ref of refs) {
|
||||
if (this.ttc.isTrackedTypeCheckFile(absoluteFrom(ref.fileName))) {
|
||||
const entry = convertToTemplateDocumentSpan(ref, this.ttc, this.driver.getProgram());
|
||||
if (entry !== null) {
|
||||
entries.set(createLocationKey(entry), entry);
|
||||
}
|
||||
} else {
|
||||
entries.set(createLocationKey(ref), ref);
|
||||
}
|
||||
}
|
||||
return Array.from(entries.values());
|
||||
}
|
||||
}
|
||||
|
||||
enum RequestKind {
|
||||
Template,
|
||||
|
@ -35,7 +90,8 @@ interface TypeScriptRequest {
|
|||
|
||||
type RequestOrigin = TemplateRequest|TypeScriptRequest;
|
||||
|
||||
export class ReferencesAndRenameBuilder {
|
||||
|
||||
export class RenameBuilder {
|
||||
private readonly ttc = this.compiler.getTemplateTypeChecker();
|
||||
|
||||
constructor(
|
||||
|
@ -125,14 +181,6 @@ export class ReferencesAndRenameBuilder {
|
|||
return allRenameLocations.length > 0 ? allRenameLocations : undefined;
|
||||
}
|
||||
|
||||
private getTsNodeAtPosition(filePath: string, position: number): ts.Node|null {
|
||||
const sf = this.driver.getProgram().getSourceFile(filePath);
|
||||
if (!sf) {
|
||||
return null;
|
||||
}
|
||||
return findTightestNode(sf, position) ?? null;
|
||||
}
|
||||
|
||||
findRenameLocationsAtTypescriptPosition(
|
||||
filePath: string, position: number,
|
||||
requestOrigin: RequestOrigin): readonly ts.RenameLocation[]|undefined {
|
||||
|
@ -181,54 +229,11 @@ export class ReferencesAndRenameBuilder {
|
|||
});
|
||||
}
|
||||
|
||||
getReferencesAtPosition(filePath: string, position: number): ts.ReferenceEntry[]|undefined {
|
||||
this.ttc.generateAllTypeCheckBlocks();
|
||||
|
||||
return this.compiler.perfRecorder.inPhase(PerfPhase.LsReferencesAndRenames, () => {
|
||||
const templateInfo = getTemplateInfoAtPosition(filePath, position, this.compiler);
|
||||
if (templateInfo === undefined) {
|
||||
return this.getReferencesAtTypescriptPosition(filePath, position);
|
||||
private getTsNodeAtPosition(filePath: string, position: number): ts.Node|null {
|
||||
const sf = this.driver.getProgram().getSourceFile(filePath);
|
||||
if (!sf) {
|
||||
return null;
|
||||
}
|
||||
return this.getReferencesAtTemplatePosition(templateInfo, position);
|
||||
});
|
||||
}
|
||||
|
||||
private getReferencesAtTemplatePosition(templateInfo: TemplateInfo, position: number):
|
||||
ts.ReferenceEntry[]|undefined {
|
||||
const allTargetDetails = getTargetDetailsAtTemplatePosition(templateInfo, position, this.ttc);
|
||||
if (allTargetDetails === null) {
|
||||
return undefined;
|
||||
}
|
||||
const allReferences: ts.ReferenceEntry[] = [];
|
||||
for (const targetDetails of allTargetDetails) {
|
||||
for (const location of targetDetails.typescriptLocations) {
|
||||
const refs = this.getReferencesAtTypescriptPosition(location.fileName, location.position);
|
||||
if (refs !== undefined) {
|
||||
allReferences.push(...refs);
|
||||
}
|
||||
}
|
||||
}
|
||||
return allReferences.length > 0 ? allReferences : undefined;
|
||||
}
|
||||
|
||||
private getReferencesAtTypescriptPosition(fileName: string, position: number):
|
||||
ts.ReferenceEntry[]|undefined {
|
||||
const refs = this.tsLS.getReferencesAtPosition(fileName, position);
|
||||
if (refs === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const entries: Map<string, ts.ReferenceEntry> = new Map();
|
||||
for (const ref of refs) {
|
||||
if (this.ttc.isTrackedTypeCheckFile(absoluteFrom(ref.fileName))) {
|
||||
const entry = convertToTemplateDocumentSpan(ref, this.ttc, this.driver.getProgram());
|
||||
if (entry !== null) {
|
||||
entries.set(createLocationKey(entry), entry);
|
||||
}
|
||||
} else {
|
||||
entries.set(createLocationKey(ref), ref);
|
||||
}
|
||||
}
|
||||
return Array.from(entries.values());
|
||||
return findTightestNode(sf, position) ?? null;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue