Skip to content

Commit 5369b37

Browse files
author
Andy Hanson
committed
Make GetEditsForFileRenameRequestArgs not extend FileRequestArgs
1 parent 3bab6af commit 5369b37

File tree

6 files changed

+65
-23
lines changed

6 files changed

+65
-23
lines changed

src/compiler/utilities.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -7494,7 +7494,11 @@ namespace ts {
74947494
}
74957495
}
74967496

7497-
// Reserved characters, forces escaping of any non-word (or digit), non-whitespace character.
7497+
export function startsWithDirectory(path: string, dirPath: string): boolean {
7498+
return tryRemoveDirectoryPrefix(path, dirPath) !== undefined;
7499+
}
7500+
7501+
// Reserved characters, forces escaping of any non-word (or digit), non-whitespace character.
74987502
// It may be inefficient (we could just match (/[-[\]{}()*+?.,\\^$|#\s]/g), but this is future
74997503
// proof.
75007504
const reservedCharacterPattern = /[^\w\s\/]/g;

src/server/editorServices.ts

+24-10
Original file line numberDiff line numberDiff line change
@@ -692,17 +692,31 @@ namespace ts.server {
692692
return this.findExternalProjectByProjectName(projectName) || this.findConfiguredProjectByProjectName(toNormalizedPath(projectName));
693693
}
694694

695-
getDefaultProjectForFile(fileName: NormalizedPath, ensureProject: boolean): Project | undefined {
696-
let scriptInfo = this.getScriptInfoForNormalizedPath(fileName);
697-
if (ensureProject && (!scriptInfo || scriptInfo.isOrphan())) {
698-
this.ensureProjectStructuresUptoDate();
699-
scriptInfo = this.getScriptInfoForNormalizedPath(fileName);
700-
if (!scriptInfo) {
701-
return Errors.ThrowNoProject();
695+
getDefaultProjectForFile(fileName: NormalizedPath, ensureProject = false): Project | undefined {
696+
const scriptInfo = this.getScriptInfoForNormalizedPath(fileName);
697+
return scriptInfo && !scriptInfo.isOrphan() ? scriptInfo.getDefaultProject() : ensureProject ? this.doEnsureDefaultProjectForFile(fileName) : undefined;
698+
}
699+
700+
ensureDefaultProjectForFile(fileName: NormalizedPath): Project {
701+
return this.getDefaultProjectForFile(fileName) || this.doEnsureDefaultProjectForFile(fileName);
702+
}
703+
704+
private doEnsureDefaultProjectForFile(fileName: NormalizedPath): Project {
705+
this.ensureProjectStructuresUptoDate();
706+
const scriptInfo = this.getScriptInfoForNormalizedPath(fileName);
707+
return scriptInfo ? scriptInfo.getDefaultProject() : Errors.ThrowNoProject();
708+
}
709+
710+
/* @internal */
711+
tryGetSomeFileInDirectory(directoryPath: NormalizedPath): { readonly file: NormalizedPath, readonly project: Project } | undefined {
712+
const scriptInfo = forEachEntry(this.filenameToScriptInfo, scriptInfo => {
713+
if (startsWithDirectory(scriptInfo.path, directoryPath)) {
714+
return scriptInfo;
702715
}
703-
return scriptInfo.getDefaultProject();
704-
}
705-
return scriptInfo && !scriptInfo.isOrphan() ? scriptInfo.getDefaultProject() : undefined;
716+
});
717+
if (!scriptInfo) return undefined;
718+
const file = toNormalizedPath(scriptInfo.path);
719+
return { file, project: this.ensureDefaultProjectForFile(file) };
706720
}
707721

708722
getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string) {

src/server/protocol.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -625,9 +625,8 @@ namespace ts.server.protocol {
625625
arguments: GetEditsForFileRenameRequestArgs;
626626
}
627627

628-
// Note: The file from FileRequestArgs is just any file in the project.
629-
// We will generate code changes for every file in that project, so the choice is arbitrary.
630-
export interface GetEditsForFileRenameRequestArgs extends FileRequestArgs {
628+
/** Note: Paths may also be directories. */
629+
export interface GetEditsForFileRenameRequestArgs {
631630
readonly oldFilePath: string;
632631
readonly newFilePath: string;
633632
}

src/server/session.ts

+23-6
Original file line numberDiff line numberDiff line change
@@ -1142,15 +1142,27 @@ namespace ts.server {
11421142
return this.getPosition(args, scriptInfo);
11431143
}
11441144

1145-
private getFileAndProject(args: protocol.FileRequestArgs): { file: NormalizedPath, project: Project } {
1145+
private getFileAndProject(args: protocol.FileRequestArgs): FileAndProject {
11461146
return this.getFileAndProjectWorker(args.file, args.projectFileName);
11471147
}
11481148

1149+
private getFileAndProjectForFileRename(args: protocol.GetEditsForFileRenameRequestArgs): FileAndProject {
1150+
const oldFilePath = toNormalizedPath(args.oldFilePath);
1151+
const oldProject = this.projectService.getDefaultProjectForFile(oldFilePath);
1152+
if (oldProject) return { file: oldFilePath, project: oldProject };
1153+
1154+
const newFilePath = toNormalizedPath(args.newFilePath);
1155+
const newProject = this.projectService.getDefaultProjectForFile(newFilePath);
1156+
if (newProject) return { file: newFilePath, project: newProject };
1157+
1158+
return Debug.assertDefined(this.projectService.tryGetSomeFileInDirectory(oldFilePath) || this.projectService.tryGetSomeFileInDirectory(newFilePath));
1159+
}
1160+
11491161
private getFileAndLanguageServiceForSyntacticOperation(args: protocol.FileRequestArgs) {
11501162
// Since this is syntactic operation, there should always be project for the file
11511163
// we wouldnt have to ensure project but rather throw if we dont get project
11521164
const file = toNormalizedPath(args.file);
1153-
const project = this.getProject(args.projectFileName) || this.projectService.getDefaultProjectForFile(file, /*ensureProject*/ false);
1165+
const project = this.getProject(args.projectFileName) || this.projectService.getDefaultProjectForFile(file);
11541166
if (!project) {
11551167
return Errors.ThrowNoProject();
11561168
}
@@ -1162,7 +1174,7 @@ namespace ts.server {
11621174

11631175
private getFileAndProjectWorker(uncheckedFileName: string, projectFileName: string | undefined): { file: NormalizedPath, project: Project } {
11641176
const file = toNormalizedPath(uncheckedFileName);
1165-
const project = this.getProject(projectFileName) || this.projectService.getDefaultProjectForFile(file, /*ensureProject*/ true)!; // TODO: GH#18217
1177+
const project = this.getProject(projectFileName) || this.projectService.ensureDefaultProjectForFile(file);
11661178
return { file, project };
11671179
}
11681180

@@ -1454,7 +1466,7 @@ namespace ts.server {
14541466
private createCheckList(fileNames: string[], defaultProject?: Project): PendingErrorCheck[] {
14551467
return mapDefined<string, PendingErrorCheck>(fileNames, uncheckedFileName => {
14561468
const fileName = toNormalizedPath(uncheckedFileName);
1457-
const project = defaultProject || this.projectService.getDefaultProjectForFile(fileName, /*ensureProject*/ false);
1469+
const project = defaultProject || this.projectService.getDefaultProjectForFile(fileName);
14581470
return project && { fileName, project };
14591471
});
14601472
}
@@ -1731,7 +1743,7 @@ namespace ts.server {
17311743
}
17321744

17331745
private getEditsForFileRename(args: protocol.GetEditsForFileRenameRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.FileCodeEdits> | ReadonlyArray<FileTextChanges> {
1734-
const { file, project } = this.getFileAndProject(args);
1746+
const { file, project } = this.getFileAndProjectForFileRename(args);
17351747
const changes = project.getLanguageService().getEditsForFileRename(toNormalizedPath(args.oldFilePath), toNormalizedPath(args.newFilePath), this.getFormatOptions(file), this.getPreferences(file));
17361748
return simplifiedResult ? this.mapTextChangesToCodeEdits(project, changes) : changes;
17371749
}
@@ -1852,7 +1864,7 @@ namespace ts.server {
18521864
const lowPriorityFiles: NormalizedPath[] = [];
18531865
const veryLowPriorityFiles: NormalizedPath[] = [];
18541866
const normalizedFileName = toNormalizedPath(fileName);
1855-
const project = this.projectService.getDefaultProjectForFile(normalizedFileName, /*ensureProject*/ true)!;
1867+
const project = this.projectService.ensureDefaultProjectForFile(normalizedFileName);
18561868
for (const fileNameInProject of fileNamesInProject) {
18571869
if (this.getCanonicalFileName(fileNameInProject) === this.getCanonicalFileName(fileName)) {
18581870
highPriorityFiles.push(fileNameInProject);
@@ -2295,6 +2307,11 @@ namespace ts.server {
22952307
}
22962308
}
22972309

2310+
interface FileAndProject {
2311+
readonly file: NormalizedPath;
2312+
readonly project: Project;
2313+
}
2314+
22982315
function mapTextChangesToCodeEdits(textChanges: FileTextChanges, sourceFile: SourceFile | undefined): protocol.FileCodeEdits {
22992316
Debug.assert(!!textChanges.isNewFile === !sourceFile);
23002317
if (sourceFile) {

src/testRunner/unittests/tsserverProjectSystem.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3097,7 +3097,7 @@ namespace ts.projectSystem {
30973097
checkProjectRootFiles(project, [file.path]);
30983098
checkProjectActualFiles(project, [file.path, libFile.path]);
30993099

3100-
assert.strictEqual(projectService.getDefaultProjectForFile(server.toNormalizedPath(file.path), /*ensureProject*/ true), project);
3100+
assert.strictEqual(projectService.ensureDefaultProjectForFile(server.toNormalizedPath(file.path)), project);
31013101
const indexOfX = file.content.indexOf("x");
31023102
assert.deepEqual(project.getLanguageService(/*ensureSynchronized*/ true).getQuickInfoAtPosition(file.path, indexOfX), {
31033103
kind: ScriptElementKind.variableElement,

tests/baselines/reference/api/tsserverlibrary.d.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -7252,6 +7252,7 @@ declare namespace ts {
72527252
function containsPath(parent: string, child: string, ignoreCase?: boolean): boolean;
72537253
function containsPath(parent: string, child: string, currentDirectory: string, ignoreCase?: boolean): boolean;
72547254
function tryRemoveDirectoryPrefix(path: string, dirPath: string): string | undefined;
7255+
function startsWithDirectory(path: string, dirPath: string): boolean;
72557256
function hasExtension(fileName: string): boolean;
72567257
const commonPackageFolders: ReadonlyArray<string>;
72577258
function getRegularExpressionForWildcard(specs: ReadonlyArray<string> | undefined, basePath: string, usage: "files" | "directories" | "exclude"): string | undefined;
@@ -12437,7 +12438,7 @@ declare namespace ts.server.protocol {
1243712438
command: CommandTypes.GetEditsForFileRename;
1243812439
arguments: GetEditsForFileRenameRequestArgs;
1243912440
}
12440-
interface GetEditsForFileRenameRequestArgs extends FileRequestArgs {
12441+
interface GetEditsForFileRenameRequestArgs {
1244112442
readonly oldFilePath: string;
1244212443
readonly newFilePath: string;
1244312444
}
@@ -13800,7 +13801,13 @@ declare namespace ts.server {
1380013801
private delayUpdateProjectGraphs;
1380113802
setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.ExternalProjectCompilerOptions, projectRootPath?: string): void;
1380213803
findProject(projectName: string): Project | undefined;
13803-
getDefaultProjectForFile(fileName: NormalizedPath, ensureProject: boolean): Project | undefined;
13804+
getDefaultProjectForFile(fileName: NormalizedPath, ensureProject?: boolean): Project | undefined;
13805+
ensureDefaultProjectForFile(fileName: NormalizedPath): Project;
13806+
private doEnsureDefaultProjectForFile;
13807+
tryGetSomeFileInDirectory(directoryPath: NormalizedPath): {
13808+
readonly file: NormalizedPath;
13809+
readonly project: Project;
13810+
} | undefined;
1380413811
getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string): ScriptInfo | undefined;
1380513812
private ensureProjectStructuresUptoDate;
1380613813
getFormatCodeOptions(file: NormalizedPath): FormatCodeSettings;
@@ -13988,6 +13995,7 @@ declare namespace ts.server {
1398813995
private getPosition;
1398913996
private getPositionInFile;
1399013997
private getFileAndProject;
13998+
private getFileAndProjectForFileRename;
1399113999
private getFileAndLanguageServiceForSyntacticOperation;
1399214000
private getFileAndProjectWorker;
1399314001
private getOutliningSpans;

0 commit comments

Comments
 (0)