Skip to content

Commit 5656f35

Browse files
committed
Introduce an organizeImports command
In phase 1, it coalesces imports from the same module and sorts the results, but does not remove unused imports. Some trivia is lost during coalescing, but none should be duplicated.
1 parent cfc234f commit 5656f35

File tree

16 files changed

+857
-0
lines changed

16 files changed

+857
-0
lines changed

Jakefile.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ var harnessSources = harnessCoreSources.concat([
141141
"typingsInstaller.ts",
142142
"projectErrors.ts",
143143
"matchFiles.ts",
144+
"organizeImports.ts",
144145
"initializeTSConfig.ts",
145146
"extractConstants.ts",
146147
"extractFunctions.ts",

src/harness/harnessLanguageService.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,9 @@ namespace Harness.LanguageService {
522522
getApplicableRefactors(): ts.ApplicableRefactorInfo[] {
523523
throw new Error("Not supported on the shim.");
524524
}
525+
organizeImports(_scope: ts.OrganizeImportsScope, _formatOptions: ts.FormatCodeSettings): ReadonlyArray<ts.FileTextChanges> {
526+
throw new Error("Not supported on the shim.");
527+
}
525528
getEmitOutput(fileName: string): ts.EmitOutput {
526529
return unwrapJSONCallResult(this.shim.getEmitOutput(fileName));
527530
}

src/harness/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
"./unittests/tsserverProjectSystem.ts",
118118
"./unittests/tscWatchMode.ts",
119119
"./unittests/matchFiles.ts",
120+
"./unittests/organizeImports.ts",
120121
"./unittests/initializeTSConfig.ts",
121122
"./unittests/compileOnSave.ts",
122123
"./unittests/typingsInstaller.ts",

src/harness/unittests/organizeImports.ts

Lines changed: 426 additions & 0 deletions
Large diffs are not rendered by default.

src/harness/unittests/session.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ namespace ts.server {
262262
CommandNames.GetApplicableRefactors,
263263
CommandNames.GetEditsForRefactor,
264264
CommandNames.GetEditsForRefactorFull,
265+
CommandNames.OrganizeImports,
266+
CommandNames.OrganizeImportsFull,
265267
];
266268

267269
it("should not throw when commands are executed with invalid arguments", () => {

src/server/client.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,10 @@ namespace ts.server {
629629
};
630630
}
631631

632+
organizeImports(_scope: OrganizeImportsScope, _formatOptions: FormatCodeSettings): ReadonlyArray<FileTextChanges> {
633+
return notImplemented();
634+
}
635+
632636
private convertCodeEditsToTextChanges(edits: protocol.FileCodeEdits[]): FileTextChanges[] {
633637
return edits.map(edit => {
634638
const fileName = edit.fileName;

src/server/protocol.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ namespace ts.server.protocol {
113113
/* @internal */
114114
GetEditsForRefactorFull = "getEditsForRefactor-full",
115115

116+
OrganizeImports = "organizeImports",
117+
/* @internal */
118+
OrganizeImportsFull = "organizeImports-full",
119+
116120
// NOTE: If updating this, be sure to also update `allCommandNames` in `harness/unittests/session.ts`.
117121
}
118122

@@ -547,6 +551,27 @@ namespace ts.server.protocol {
547551
renameFilename?: string;
548552
}
549553

554+
/**
555+
* Organize imports by:
556+
* 1) Removing unused imports
557+
* 2) Coalescing imports from the same module
558+
* 3) Sorting imports
559+
*/
560+
export interface OrganizeImportsRequest extends Request {
561+
command: CommandTypes.OrganizeImports;
562+
arguments: OrganizeImportsRequestArgs;
563+
}
564+
565+
export type OrganizeImportsScope = GetCombinedCodeFixScope;
566+
567+
export interface OrganizeImportsRequestArgs {
568+
scope: OrganizeImportsScope;
569+
}
570+
571+
export interface OrganizeImportsResponse extends Response {
572+
edits: ReadonlyArray<FileCodeEdits>;
573+
}
574+
550575
/**
551576
* Request for the available codefixes at a specific position.
552577
*/

src/server/session.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,6 +1597,19 @@ namespace ts.server {
15971597
}
15981598
}
15991599

1600+
private organizeImports({ scope }: protocol.OrganizeImportsRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.FileCodeEdits> | ReadonlyArray<FileTextChanges> {
1601+
Debug.assert(scope.type === "file");
1602+
const { file, project } = this.getFileAndProject(scope.args);
1603+
const formatOptions = this.projectService.getFormatCodeOptions(file);
1604+
const changes = project.getLanguageService().organizeImports({ type: "file", fileName: file }, formatOptions);
1605+
if (simplifiedResult) {
1606+
return this.mapTextChangesToCodeEdits(project, changes);
1607+
}
1608+
else {
1609+
return changes;
1610+
}
1611+
}
1612+
16001613
private getCodeFixes(args: protocol.CodeFixRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.CodeAction> | ReadonlyArray<CodeAction> {
16011614
if (args.errorCodes.length === 0) {
16021615
return undefined;
@@ -2041,6 +2054,12 @@ namespace ts.server {
20412054
},
20422055
[CommandNames.GetEditsForRefactorFull]: (request: protocol.GetEditsForRefactorRequest) => {
20432056
return this.requiredResponse(this.getEditsForRefactor(request.arguments, /*simplifiedResult*/ false));
2057+
},
2058+
[CommandNames.OrganizeImports]: (request: protocol.OrganizeImportsRequest) => {
2059+
return this.requiredResponse(this.organizeImports(request.arguments, /*simplifiedResult*/ true));
2060+
},
2061+
[CommandNames.OrganizeImportsFull]: (request: protocol.OrganizeImportsRequest) => {
2062+
return this.requiredResponse(this.organizeImports(request.arguments, /*simplifiedResult*/ false));
20442063
}
20452064
});
20462065

0 commit comments

Comments
 (0)