Skip to content

Commit afe9660

Browse files
testforstephenfbricon
authored andcommitted
Support advanced organizeImports to resolve ambiguous imports (#850)
Signed-off-by: Jinbo Wang <jinbwan@microsoft.com>
1 parent e07d2da commit afe9660

File tree

5 files changed

+88
-5
lines changed

5 files changed

+88
-5
lines changed

src/commands.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,12 @@ export namespace Commands {
114114
* Open settings.json
115115
*/
116116
export const OPEN_JSON_SETTINGS = 'workbench.action.openSettingsJson';
117+
/**
118+
* Organize imports.
119+
*/
120+
export const ORGANIZE_IMPORTS = "java.action.organizeImports";
121+
/**
122+
* Choose type to import.
123+
*/
124+
export const CHOOSE_IMPORTS = "java.action.organizeImports.chooseImports";
117125
}

src/extension.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
7575
progressReportProvider: getJavaConfiguration().get('progressReports.enabled'),
7676
classFileContentsSupport:true,
7777
overrideMethodsPromptSupport:true,
78-
hashCodeEqualsPromptSupport:true
78+
hashCodeEqualsPromptSupport:true,
79+
advancedOrganizeImportsSupport:true
7980
},
8081
triggerFiles: getTriggerFiles()
8182
},

src/protocol.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
import { RequestType, NotificationType, TextDocumentIdentifier, ExecuteCommandParams, CodeActionParams, WorkspaceEdit } from 'vscode-languageclient';
4-
import { Command } from 'vscode';
4+
import { Command, Range } from 'vscode';
55

66
/**
77
* The message type. Copied from vscode protocol
@@ -173,4 +173,18 @@ export interface GenerateHashCodeEqualsParams {
173173

174174
export namespace GenerateHashCodeEqualsRequest {
175175
export const type = new RequestType<GenerateHashCodeEqualsParams, WorkspaceEdit, void, void>('java/generateHashCodeEquals');
176+
}
177+
178+
export namespace OrganizeImportsRequest {
179+
export const type = new RequestType<CodeActionParams, WorkspaceEdit, void, void>('java/organizeImports');
180+
}
181+
182+
export interface ImportCandidate {
183+
fullyQualifiedName: string;
184+
id: string;
185+
}
186+
187+
export interface ImportSelection {
188+
candidates: ImportCandidate[];
189+
range: Range;
176190
}

src/sourceAction.ts

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
'use strict';
22

3-
import { commands, window, ExtensionContext } from 'vscode';
3+
import { commands, window, ExtensionContext, Range, ViewColumn, Uri, Disposable} from 'vscode';
44
import { CodeActionParams, LanguageClient } from 'vscode-languageclient';
55
import { Commands } from './commands';
66
import { applyWorkspaceEdit } from './extension';
7-
import { ListOverridableMethodsRequest, AddOverridableMethodsRequest, CheckHashCodeEqualsStatusRequest, GenerateHashCodeEqualsRequest } from './protocol';
7+
import { ListOverridableMethodsRequest, AddOverridableMethodsRequest, CheckHashCodeEqualsStatusRequest, GenerateHashCodeEqualsRequest,
8+
OrganizeImportsRequest, ImportCandidate, ImportSelection } from './protocol';
89

910
export function registerCommands(languageClient: LanguageClient, context: ExtensionContext) {
1011
registerOverrideMethodsCommand(languageClient, context);
1112
registerHashCodeEqualsCommand(languageClient, context);
13+
registerOrganizeImportsCommand(languageClient, context);
14+
registerChooseImportCommand(context);
1215
}
1316

1417
function registerOverrideMethodsCommand(languageClient: LanguageClient, context: ExtensionContext): void {
@@ -100,3 +103,58 @@ function registerHashCodeEqualsCommand(languageClient: LanguageClient, context:
100103
applyWorkspaceEdit(workspaceEdit, languageClient);
101104
}));
102105
}
106+
107+
function registerOrganizeImportsCommand(languageClient: LanguageClient, context: ExtensionContext): void {
108+
context.subscriptions.push(commands.registerCommand(Commands.ORGANIZE_IMPORTS, async (params: CodeActionParams) => {
109+
const workspaceEdit = await languageClient.sendRequest(OrganizeImportsRequest.type, params);
110+
applyWorkspaceEdit(workspaceEdit, languageClient);
111+
}));
112+
}
113+
114+
function registerChooseImportCommand(context: ExtensionContext): void {
115+
context.subscriptions.push(commands.registerCommand(Commands.CHOOSE_IMPORTS, async (uri: string, selections: ImportSelection[]) => {
116+
const chosen: ImportCandidate[] = [];
117+
const fileUri: Uri = Uri.parse(uri);
118+
for (let i = 0; i < selections.length; i++) {
119+
const selection : ImportSelection = selections[i];
120+
// Move the cursor to the code line with ambiguous import choices.
121+
await window.showTextDocument(fileUri, { preserveFocus: true, selection: selection.range, viewColumn: ViewColumn.One });
122+
const candidates: ImportCandidate[] = selection.candidates;
123+
const items = candidates.map((item) => {
124+
return {
125+
label: item.fullyQualifiedName,
126+
origin: item
127+
};
128+
});
129+
130+
const fullyQualifiedName = candidates[0].fullyQualifiedName;
131+
const typeName = fullyQualifiedName.substring(fullyQualifiedName.lastIndexOf(".") + 1);
132+
const disposables: Disposable[] = [];
133+
try {
134+
const pick = await new Promise<any>((resolve, reject) => {
135+
const input = window.createQuickPick();
136+
input.title = "Organize Imports";
137+
input.step = i + 1;
138+
input.totalSteps = selections.length;
139+
input.placeholder = `Choose type '${typeName}' to import`;
140+
input.items = items;
141+
disposables.push(
142+
input.onDidChangeSelection(items => resolve(items[0])),
143+
input.onDidHide(() => {
144+
reject(undefined);
145+
}),
146+
input
147+
);
148+
input.show();
149+
});
150+
chosen.push(pick ? pick.origin : null);
151+
} catch (err) {
152+
break;
153+
} finally {
154+
disposables.forEach(d => d.dispose());
155+
}
156+
}
157+
158+
return chosen;
159+
}));
160+
}

test/extension.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ suite('Java Language Extension', () => {
4343
Commands.LIST_SOURCEPATHS,
4444
Commands.OVERRIDE_METHODS_PROMPT,
4545
Commands.HASHCODE_EQUALS_PROMPT,
46-
Commands.OPEN_JSON_SETTINGS
46+
Commands.OPEN_JSON_SETTINGS,
47+
Commands.ORGANIZE_IMPORTS,
48+
Commands.CHOOSE_IMPORTS
4749
];
4850
let foundJavaCommands = commands.filter(function(value){
4951
return JAVA_COMMANDS.indexOf(value)>=0 || value.startsWith('java.');

0 commit comments

Comments
 (0)