Smart semicolon autocorrect#3159
Conversation
|
A few things : I noticed that for a larger project, there is a point where one can edit a source file, while the language server is still loading. Maybe we need only register the capability under Some other odd cases. Can we handle any of these ? |
Fixed |
It is related to eclipse-jdtls/eclipse.jdt.ls#2710. Checking... |
|
0061d14 to
d4e4d21
Compare
@rgrunber Could you, please, check it again. I have also implemented the backspace char the same way as in Eclipse. |
It has been fixed. |
| } | ||
| } | ||
|
|
||
| let serverReady = false; |
There was a problem hiding this comment.
Are you using this variable here because you're trying to correctly handle the semicolon in the case of the text blocks also ?
I would have really like to move this into
vscode-java/src/standardLanguageClient.ts
Line 135 in 15ddbfe
Would it make sense to create a helper method that sets :
oldPosition = null;
newPosition = null;
so we can move the "smart semicolon" code into the standard client's onReady callback ?
There was a problem hiding this comment.
Are you using this variable here because you're trying to correctly handle the semicolon in the case of the text blocks also ?
No, it isn't related to the text block. We are waiting for the server to be ready.
I would have really like to move this into
I have tried it, but I didn't succeed.
There was a problem hiding this comment.
Is there an issue with the following ? Basically I just moved all the smart semicolon logic into a new file, smartSemicolonDetection.ts. I made the oldPostion/newPosition variables global in there as well and created a helper function (setSmartSemiColonDetectionState(old, new)) that can be used to access them from the text block logic. I also called registerSmartSemicolonDetection(..) directly in the standardLanguageClient.ts code where we listen for the ServiceReady notification.
patch
diff --git a/src/extension.ts b/src/extension.ts
index 90fc982..d0de894 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -24,7 +24,7 @@ import { initialize as initializeRecommendation } from './recommendation';
import * as requirements from './requirements';
import { runtimeStatusBarProvider } from './runtimeStatusBarProvider';
import { serverStatusBarProvider } from './serverStatusBarProvider';
-import { ACTIVE_BUILD_TOOL_STATE, cleanWorkspaceFileName, getJavaServerMode, handleTextBlockClosing, onConfigurationChange, registerSmartSemicolonDetection, ServerMode } from './settings';
+import { ACTIVE_BUILD_TOOL_STATE, cleanWorkspaceFileName, getJavaServerMode, handleTextBlockClosing, onConfigurationChange, ServerMode } from './settings';
import { snippetCompletionProvider } from './snippetCompletionProvider';
import { JavaClassEditorProvider } from './javaClassEditor';
import { StandardLanguageClient } from './standardLanguageClient';
@@ -35,6 +35,7 @@ import { Telemetry } from './telemetry';
import { getMessage } from './errorUtils';
import { TelemetryService } from '@redhat-developer/vscode-redhat-telemetry/lib';
import { activationProgressNotification } from "./serverTaskPresenter";
+import { registerSmartSemicolonDetection } from './smartSemicolonDetection';
const syntaxClient: SyntaxLanguageClient = new SyntaxLanguageClient();
const standardClient: StandardLanguageClient = new StandardLanguageClient();
diff --git a/src/settings.ts b/src/settings.ts
index 8cd580f..091c8ee 100644
--- a/src/settings.ts
+++ b/src/settings.ts
@@ -7,6 +7,7 @@ import { Commands } from './commands';
import { cleanupLombokCache } from './lombokSupport';
import { ensureExists, getJavaConfiguration } from './utils';
import { apiManager } from './apiManager';
+import { setSmartSemiColonDetectionState } from './smartSemicolonDetection';
const DEFAULT_HIDDEN_FILES: string[] = ['**/.classpath', '**/.project', '**/.settings', '**/.factorypath'];
const IS_WORKSPACE_JDK_ALLOWED = "java.ls.isJdkAllowed";
@@ -29,9 +30,6 @@ export const ORGANIZE_IMPORTS_ON_PASTE = 'actionsOnPaste.organizeImports'; // ja
let oldConfig: WorkspaceConfiguration = getJavaConfiguration();
const gradleWrapperPromptDialogs = [];
-let oldPosition: Position = null;
-let newPosition: Position = null;
-
export function onConfigurationChange(workspacePath: string, context: ExtensionContext) {
return workspace.onDidChangeConfiguration(params => {
if (!params.affectsConfiguration('java')) {
@@ -334,8 +332,7 @@ export function handleTextBlockClosing(document: TextDocument, changes: readonly
}
if (lastChange.text !== '"""";') {
if (lastChange.text !== ';') {
- oldPosition = null;
- newPosition = null;
+ setSmartSemiColonDetectionState(null, null);
}
return;
}
@@ -358,68 +355,3 @@ export function handleTextBlockClosing(document: TextDocument, changes: readonly
}
}
-let serverReady = false;
-
-export function registerSmartSemicolonDetection(context: ExtensionContext) {
- apiManager.getApiInstance().serverReady().then(() => {
- serverReady = true;
- });
- context.subscriptions.push(commands.registerCommand(Commands.SMARTSEMICOLON_DETECTION_CMD, async () => {
- if (!isSemichar() && window.activeTextEditor.document.fileName.endsWith(".java")) {
- const params: SmartDetectionParams = {
- uri: window.activeTextEditor.document.uri.toString(),
- position: window.activeTextEditor!.selection.active,
- };
- const response: SmartDetectionParams = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.SMARTSEMICOLON_DETECTION, JSON.stringify(params));
- if (response !== null) {
- window.activeTextEditor!.edit(editBuilder => {
- oldPosition = window.activeTextEditor!.selection.active;
- editBuilder.insert(response.position, ";");
- window.activeTextEditor.selections = [new Selection(response.position, response.position)];
- newPosition = window.activeTextEditor!.selection.active;
- });
- return;
- }
- }
- window.activeTextEditor!.edit(editBuilder => {
- editBuilder.insert(window.activeTextEditor!.selection.active, ";");
- });
- newPosition = null;
- oldPosition = null;
- }));
- context.subscriptions.push(commands.registerCommand(Commands.SMARTSEMICOLON_DETECTION_SEMICHAR, async () => {
- if (isSemichar()) {
- window.activeTextEditor!.edit(editBuilder => {
- editBuilder.insert(oldPosition, ";");
- const delRange = new Range(newPosition, new Position(newPosition.line, newPosition.character + 1));
- editBuilder.delete(delRange);
- window.activeTextEditor.selections = [new Selection(oldPosition, oldPosition)];
- oldPosition = null;
- newPosition = null;
- });
- return;
- }
- window.activeTextEditor!.edit(() => {
- commands.executeCommand("deleteLeft");
- });
- oldPosition = null;
- newPosition = null;
- }));
-}
-
-interface SmartDetectionParams {
- uri: String;
- position: Position;
-}
-
-function isSemichar() {
- const enabled = getJavaConfiguration().get<boolean>("edit.smartSemicolonDetection");
- const isSemichar = serverReady && window.activeTextEditor.selections.length === 1 && enabled && oldPosition !== null && newPosition !== null;
- if (isSemichar) {
- const active = window.activeTextEditor!.selection.active;
- const prev = new Position(active.line, active.character === 0 ? 0 : active.character - 1);
- return newPosition.isEqual(prev);
- }
- return isSemichar;
-}
-
diff --git a/src/smartSemicolonDetection.ts b/src/smartSemicolonDetection.ts
new file mode 100644
index 0000000..fceb270
--- /dev/null
+++ b/src/smartSemicolonDetection.ts
@@ -0,0 +1,73 @@
+'use strict';
+
+import { commands, ExtensionContext, Position, Range, Selection, window } from 'vscode';
+import { Commands } from './commands';
+import { getJavaConfiguration } from './utils';
+
+let oldPosition: Position = null;
+let newPosition: Position = null;
+
+export function registerSmartSemicolonDetection(context: ExtensionContext) {
+ context.subscriptions.push(commands.registerCommand(Commands.SMARTSEMICOLON_DETECTION_CMD, async () => {
+ if (!isSemichar() && window.activeTextEditor.document.fileName.endsWith(".java")) {
+ const params: SmartDetectionParams = {
+ uri: window.activeTextEditor.document.uri.toString(),
+ position: window.activeTextEditor!.selection.active,
+ };
+ const response: SmartDetectionParams = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.SMARTSEMICOLON_DETECTION, JSON.stringify(params));
+ if (response !== null) {
+ window.activeTextEditor!.edit(editBuilder => {
+ oldPosition = window.activeTextEditor!.selection.active;
+ editBuilder.insert(response.position, ";");
+ window.activeTextEditor.selections = [new Selection(response.position, response.position)];
+ newPosition = window.activeTextEditor!.selection.active;
+ });
+ return;
+ }
+ }
+ window.activeTextEditor!.edit(editBuilder => {
+ editBuilder.insert(window.activeTextEditor!.selection.active, ";");
+ });
+ newPosition = null;
+ oldPosition = null;
+ }));
+ context.subscriptions.push(commands.registerCommand(Commands.SMARTSEMICOLON_DETECTION_SEMICHAR, async () => {
+ if (isSemichar()) {
+ window.activeTextEditor!.edit(editBuilder => {
+ editBuilder.insert(oldPosition, ";");
+ const delRange = new Range(newPosition, new Position(newPosition.line, newPosition.character + 1));
+ editBuilder.delete(delRange);
+ window.activeTextEditor.selections = [new Selection(oldPosition, oldPosition)];
+ oldPosition = null;
+ newPosition = null;
+ });
+ return;
+ }
+ window.activeTextEditor!.edit(() => {
+ commands.executeCommand("deleteLeft");
+ });
+ oldPosition = null;
+ newPosition = null;
+ }));
+}
+
+interface SmartDetectionParams {
+ uri: String;
+ position: Position;
+}
+
+function isSemichar() {
+ const enabled = getJavaConfiguration().get<boolean>("edit.smartSemicolonDetection");
+ const isSemichar = window.activeTextEditor.selections.length === 1 && enabled && oldPosition !== null && newPosition !== null;
+ if (isSemichar) {
+ const active = window.activeTextEditor!.selection.active;
+ const prev = new Position(active.line, active.character === 0 ? 0 : active.character - 1);
+ return newPosition.isEqual(prev);
+ }
+ return isSemichar;
+}
+
+export function setSmartSemiColonDetectionState(oldPos: Position, newPos: Position) {
+ oldPosition = oldPos;
+ newPos = newPos;
+}
\ No newline at end of file
diff --git a/src/standardLanguageClient.ts b/src/standardLanguageClient.ts
index 6b07f11..2b0f6a6 100644
--- a/src/standardLanguageClient.ts
+++ b/src/standardLanguageClient.ts
@@ -40,6 +40,7 @@ import { getAllJavaProjects, getJavaConfig, getJavaConfiguration } from "./utils
import { Telemetry } from "./telemetry";
import { TelemetryEvent } from "@redhat-developer/vscode-redhat-telemetry/lib";
import { registerDocumentValidationListener } from './diagnostic';
+import { registerSmartSemicolonDetection } from './smartSemicolonDetection';
const extensionName = 'Language Support for Java';
const GRADLE_CHECKSUM = "gradle/checksum/prompt";
@@ -137,6 +138,7 @@ export class StandardLanguageClient {
// clients may not have properly configured documentPaste
logger.error(error);
}
+ registerSmartSemicolonDetection(context);
activationProgressNotification.hide();
if (!hasImported) {
showImportFinishNotification(context);There was a problem hiding this comment.
It works fine. I have updated the PR.
9d99d16 to
70ed480
Compare
|
@rgrunber I have updated this PR and eclipse-jdtls/eclipse.jdt.ls#2710 |
Signed-off-by: Snjezana Peco <snjezana.peco@redhat.com>
b63ef9e to
a23bdc3
Compare
There was a problem hiding this comment.
Overall, this looks good. Just some very minor things to handle. Then we can merge and address any other issues.
There's another small thing I noticed but I'm open to handling it in a separate PR to avoid complicating this one further.
We set javaLSReadyin Started at
vscode-java/src/standardLanguageClient.ts
Lines 152 to 155 in a60b5e4
However, we only register the semicolon detection commands in ServiceReady . For large projects there can be a gap between Started and ServiceReady so there is a moment where the commands may be activated (after Started) but before we have registerd the command (at ServiceReady). The solution is probably to create a separate context state that's triggered within ServiceReady. Update: According to the logs started+serviceready happen not even a second apart so maybe I've just been lucky reproducing the warning. Let's say it's lower priority and we can address this part later.
|
@rgrunber I have updated the PR. |
|
There's another issue. Even when Also it looks to me like the purpose of |
Fixed.
Fixed. |
Contributed by Roland Grunberg <rgrunber@redhat.com>
This reverts commit 3ad9b16.
This reverts commit 3ad9b16.
This reverts commit 3ad9b16.






Fixes #703
Requires eclipse-jdtls/eclipse.jdt.ls#2710