Skip to content

Commit cab7674

Browse files
NikolasKomonenfbricon
authored andcommitted
Pasting code into empty file will trigger organize imports
Issue #1075 New preference: java.paste.organizeImportsOnPaste Signed-off-by: Nikolas Komonen <nikolaskomonen@gmail.com>
1 parent d6cd06d commit cab7674

File tree

5 files changed

+96
-6
lines changed

5 files changed

+96
-6
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ The following settings are supported:
116116
* `java.codeGeneration.toString.listArrayContents`: List contents of arrays instead of using native toString(). Defaults to `true`.
117117
* `java.codeGeneration.toString.limitElements`: Limit number of items in arrays/collections/maps to list, if 0 then list all. Defaults to `0`.
118118
* `java.selectionRange.enabled`: Enable/disable Smart Selection support for Java. Disabling this option will not affect the VS Code built-in word-based and bracket-based smart selection.
119+
* `java.actionsOnPaste.organizeImports`: Triggers "Organize imports" when java code is pasted into an empty file.
119120

120121
Troubleshooting
121122
===============

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,12 @@
388388
"default": true,
389389
"description": "Enable/disable Smart Selection support for Java. Disabling this option will not affect the VS Code built-in word-based and bracket-based smart selection.",
390390
"scope": "window"
391+
},
392+
"java.actionsOnPaste.organizeImports": {
393+
"type": "boolean",
394+
"description": "Triggers 'Organize imports' when java code is pasted into an empty file.",
395+
"default": true,
396+
"scope": "window"
391397
}
392398
}
393399
},

src/extension.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import * as sourceAction from './sourceAction';
2020
import * as refactorAction from './refactorAction';
2121
import * as net from 'net';
2222
import { getJavaConfiguration } from './utils';
23-
import { onConfigurationChange, excludeProjectSettingsFiles } from './settings';
23+
import { onConfigurationChange, excludeProjectSettingsFiles, initializeSettings } from './settings';
2424
import { logger, initializeLogFile } from './log';
2525
import glob = require('glob');
2626

@@ -388,6 +388,7 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
388388
buildpath.registerCommands(context);
389389
sourceAction.registerCommands(languageClient, context);
390390
refactorAction.registerCommands(languageClient, context);
391+
initializeSettings(languageClient, context); // may need to move in the future
391392

392393
context.subscriptions.push(window.onDidChangeActiveTextEditor((editor) => {
393394
toggleItem(editor, item);
@@ -435,7 +436,7 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
435436

436437
context.subscriptions.push(commands.registerCommand(Commands.CLEAN_WORKSPACE, () => cleanWorkspace(workspacePath)));
437438

438-
context.subscriptions.push(onConfigurationChange());
439+
context.subscriptions.push(onConfigurationChange(languageClient, context));
439440
toggleItem(window.activeTextEditor, item);
440441
});
441442
});

src/settings.ts

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
import { window, Uri, workspace, WorkspaceConfiguration, commands, ConfigurationTarget, env } from 'vscode';
3+
import { window, Uri, workspace, WorkspaceConfiguration, commands, ConfigurationTarget, env, ExtensionContext, TextEditor, Range, Disposable } from 'vscode';
44
import { LanguageClient } from 'vscode-languageclient';
55
import { Commands } from './commands';
66
import { getJavaConfiguration } from './utils';
@@ -14,10 +14,13 @@ const changeItem = {
1414
};
1515

1616
const EXCLUDE_FILE_CONFIG = 'configuration.checkProjectSettingsExclusions';
17+
export const ORGANIZE_IMPORTS_ON_PASTE = 'actionsOnPaste.organizeImports'; // java.actionsOnPaste.organizeImports
18+
// index of the paste disposable in the subscriptions array
19+
let pasteSubscriptionIndex;
1720

1821
let oldConfig: WorkspaceConfiguration = getJavaConfiguration();
1922

20-
export function onConfigurationChange() {
23+
export function onConfigurationChange(languageClient: LanguageClient, context: ExtensionContext) {
2124
return workspace.onDidChangeConfiguration(params => {
2225
if (!params.affectsConfiguration('java')) {
2326
return;
@@ -30,16 +33,27 @@ export function onConfigurationChange() {
3033
const msg = `Java Language Server configuration changed, please restart ${env.appName}.`;
3134
const action = 'Restart Now';
3235
const restartId = Commands.RELOAD_WINDOW;
33-
oldConfig = newConfig;
3436
window.showWarningMessage(msg, action).then((selection) => {
3537
if (action === selection) {
3638
commands.executeCommand(restartId);
3739
}
3840
});
3941
}
42+
handleJavaPasteConfigurationChange(languageClient, context, newConfig);
43+
// update old config
44+
oldConfig = newConfig;
4045
});
4146
}
4247

48+
/**
49+
* Starting point for any settings that need to be handled when the server starts
50+
* @param languageClient
51+
* @param context
52+
*/
53+
export function initializeSettings(languageClient: LanguageClient, context: ExtensionContext) {
54+
handleInitialConfigurations(languageClient, context, getJavaConfiguration());
55+
}
56+
4357
export function excludeProjectSettingsFiles() {
4458
if (workspace.workspaceFolders && workspace.workspaceFolders.length) {
4559
workspace.workspaceFolders.forEach((folder) => {
@@ -114,3 +128,71 @@ export function getJavaEncoding(): string {
114128
}
115129
return javaEncoding;
116130
}
131+
132+
export function handleInitialConfigurations(languageClient: LanguageClient, context: ExtensionContext, newConfig: WorkspaceConfiguration) {
133+
// organize imports on paste registration
134+
if (newConfig.get(ORGANIZE_IMPORTS_ON_PASTE)) {
135+
registerOverridePasteCommand(languageClient, context);
136+
}
137+
}
138+
139+
export function handleJavaPasteConfigurationChange(languageClient: LanguageClient, context: ExtensionContext, newConfig: WorkspaceConfiguration) {
140+
const oldOrganizeImportsOnPaste = oldConfig.get(ORGANIZE_IMPORTS_ON_PASTE);
141+
const newOrganizeImportsOnPaste = newConfig.get(ORGANIZE_IMPORTS_ON_PASTE);
142+
if (oldOrganizeImportsOnPaste !== newOrganizeImportsOnPaste) {
143+
if (newOrganizeImportsOnPaste === true) {
144+
registerOverridePasteCommand(languageClient, context);
145+
}
146+
else {
147+
unregisterOverridePasteCommand(languageClient, context);
148+
}
149+
}
150+
}
151+
152+
export function registerOverridePasteCommand(languageClient: LanguageClient, context: ExtensionContext): void {
153+
// referencing https://github.com/gazugafan/vscode-indent-on-paste/blob/master/src/extension.ts
154+
const length = context.subscriptions.push(commands.registerCommand('editor.action.clipboardPasteAction', async () => {
155+
156+
const clipboardText: string = await env.clipboard.readText();
157+
const editor: TextEditor = window.activeTextEditor;
158+
159+
const documentText: string = editor.document.getText();
160+
161+
const isCursorOnly = editor.selection.isEmpty;
162+
let action: Thenable<boolean>;
163+
if (isCursorOnly) {
164+
action = editor.edit(textInserter => {
165+
textInserter.insert(editor.selection.start, clipboardText);
166+
});
167+
}
168+
else {
169+
const start = editor.selection.start;
170+
const end = editor.selection.end;
171+
action = editor.edit(textInserter => {
172+
textInserter.replace(new Range(start, end), clipboardText);
173+
});
174+
}
175+
176+
action.then((wasApplied) => {
177+
const hasText: boolean = documentText !== null && /\S/.test(documentText);
178+
const fileURI = editor.document.uri.toString();
179+
if (wasApplied && !hasText && fileURI.endsWith(".java")) { // only organizing imports if document is blank
180+
// Organize imports only requires uri from CodeActionParams
181+
const codeActionParams = { textDocument: { uri: fileURI } };
182+
commands.executeCommand(Commands.ORGANIZE_IMPORTS, codeActionParams);
183+
}
184+
});
185+
}));
186+
187+
pasteSubscriptionIndex = length - 1;
188+
languageClient.info(`Registered 'java.${ORGANIZE_IMPORTS_ON_PASTE}' command.`);
189+
}
190+
191+
export function unregisterOverridePasteCommand(languageClient: LanguageClient, context: ExtensionContext) {
192+
if (pasteSubscriptionIndex !== null) {
193+
const pasteDisposable: Disposable = context.subscriptions[pasteSubscriptionIndex];
194+
pasteDisposable.dispose();
195+
pasteSubscriptionIndex = null;
196+
languageClient.info(`Unregistered 'java.${ORGANIZE_IMPORTS_ON_PASTE}' command.`);
197+
}
198+
}

src/sourceAction.ts

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

3-
import { commands, window, ExtensionContext, Range, ViewColumn, Uri, Disposable } from 'vscode';
3+
import { commands, window, ExtensionContext, ViewColumn, Uri, Disposable } from 'vscode';
44
import { CodeActionParams, LanguageClient } from 'vscode-languageclient';
55
import { Commands } from './commands';
66
import { applyWorkspaceEdit } from './extension';

0 commit comments

Comments
 (0)