From 86c2adf9411f19d881440975ebd211064b44de60 Mon Sep 17 00:00:00 2001 From: Roland Grunberg Date: Fri, 8 Nov 2024 16:18:58 -0500 Subject: [PATCH] Add setting 'java.references.includeDeclarations'. - Control inclusion of declarations when searching for references - Also simplify the 'resolveCodeAction' middleware implementation Signed-off-by: Roland Grunberg --- README.md | 3 ++ package.json | 19 +++++++---- src/extension.ts | 83 +++++++++++++++++++++++++----------------------- 3 files changed, 59 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index e88013eb0..42e531b57 100644 --- a/README.md +++ b/README.md @@ -256,6 +256,9 @@ The following settings are supported: * `java.jdt.ls.javac.enabled`: [Experimental] Specify whether to enable Javac-based compilation in the language server. Requires running this extension with Java 23. Defaults to `off`. * `java.completion.engine`: [Experimental] Select code completion engine. Defaults to `ecj`. +New in 1.37.0 +* `java.references.includeDeclarations`: Include declarations when finding references. Defaults to `true` + Semantic Highlighting =============== [Semantic Highlighting](https://github.com/redhat-developer/vscode-java/wiki/Semantic-Highlighting) fixes numerous syntax highlighting issues with the default Java Textmate grammar. However, you might experience a few minor issues, particularly a delay when it kicks in, as it needs to be computed by the Java Language server, when opening a new file or when typing. Semantic highlighting can be disabled for all languages using the `editor.semanticHighlighting.enabled` setting, or for Java only using [language-specific editor settings](https://code.visualstudio.com/docs/getstarted/settings#_languagespecific-editor-settings). diff --git a/package.json b/package.json index 3b8106864..f702896ca 100644 --- a/package.json +++ b/package.json @@ -1422,26 +1422,33 @@ "scope": "window", "order": 30 }, + "java.references.includeDeclarations": { + "type": "boolean", + "default": true, + "description": "Include declarations when finding references.", + "scope": "window", + "order": 40 + }, "java.references.includeDecompiledSources": { "type": "boolean", "default": true, "description": "Include the decompiled sources when finding references.", "scope": "window", - "order": 40 + "order": 50 }, "java.symbols.includeSourceMethodDeclarations": { "type": "boolean", "markdownDescription": "Include method declarations from source files in symbol search.", "default": false, "scope": "window", - "order": 50 + "order": 60 }, "java.typeHierarchy.lazyLoad": { "type": "boolean", "default": false, "description": "Enable/disable lazy loading the content in type hierarchy. Lazy loading could save a lot of loading time but every type should be expanded manually to load its content.", "scope": "window", - "order": 60 + "order": 70 }, "java.inlayHints.parameterNames.enabled": { "type": "string", @@ -1458,7 +1465,7 @@ "default": "literals", "markdownDescription": "Enable/disable inlay hints for parameter names:\n```java\n\nInteger.valueOf(/* s: */ '123', /* radix: */ 10)\n \n```\n `#java.inlayHints.parameterNames.exclusions#` can be used to disable the inlay hints for methods.", "scope": "window", - "order": 70 + "order": 80 }, "java.inlayHints.parameterNames.exclusions": { "type": "array", @@ -1468,7 +1475,7 @@ "default": [], "markdownDescription": "The patterns for the methods that will be disabled to show the inlay hints. Supported pattern examples:\n - `java.lang.Math.*` - All the methods from java.lang.Math.\n - `*.Arrays.asList` - Methods named as 'asList' in the types named as 'Arrays'.\n - `*.println(*)` - Methods named as 'println'.\n - `(from, to)` - Methods with two parameters named as 'from' and 'to'.\n - `(arg*)` - Methods with one parameter whose name starts with 'arg'.", "scope": "window", - "order": 80 + "order": 90 }, "java.search.scope": { "type": "string", @@ -1483,7 +1490,7 @@ "default": "all", "markdownDescription": "Specifies the scope which must be used for search operation like \n - Find Reference\n - Call Hierarchy\n - Workspace Symbols", "scope": "window", - "order": 90 + "order": 100 } } }, diff --git a/src/extension.ts b/src/extension.ts index b0db04d5f..6a139d8d0 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -6,7 +6,7 @@ import * as fse from 'fs-extra'; import * as os from 'os'; import * as path from 'path'; import * as semver from 'semver'; -import { CodeActionContext, commands, CompletionItem, ConfigurationTarget, Diagnostic, env, EventEmitter, ExtensionContext, extensions, IndentAction, InputBoxOptions, languages, MarkdownString, QuickPickItemKind, Range, RelativePattern, SnippetString, SnippetTextEdit, TextDocument, TextEditorRevealType, UIKind, Uri, ViewColumn, window, workspace, WorkspaceConfiguration, WorkspaceEdit } from 'vscode'; +import { CodeActionContext, commands, CompletionItem, ConfigurationTarget, Diagnostic, env, EventEmitter, ExtensionContext, extensions, IndentAction, InputBoxOptions, languages, Location, MarkdownString, QuickPickItemKind, Range, RelativePattern, SnippetString, SnippetTextEdit, TextDocument, TextEditorRevealType, UIKind, Uri, ViewColumn, window, workspace, WorkspaceConfiguration, WorkspaceEdit } from 'vscode'; import { CancellationToken, CodeActionParams, CodeActionRequest, CodeActionResolveRequest, Command, CompletionRequest, DidChangeConfigurationNotification, ExecuteCommandParams, ExecuteCommandRequest, LanguageClientOptions, RevealOutputChannelOn } from 'vscode-languageclient'; import { LanguageClient } from 'vscode-languageclient/node'; import { apiManager } from './apiManager'; @@ -307,54 +307,57 @@ export async function activate(context: ExtensionContext): Promise const client: LanguageClient = standardClient.getClient(); const documentUris = []; const snippetEdits = []; - const resolveCodeAction = async (item, token) => { - return client.sendRequest(CodeActionResolveRequest.type, client.code2ProtocolConverter.asCodeActionSync(item), token).then(async (result) => { - if (token.isCancellationRequested) { - return item; - } - const docChanges = result.edit !== undefined ? result.edit.documentChanges : undefined; - if (docChanges !== undefined) { - for (const docChange of docChanges) { - if ("textDocument" in docChange) { - for (const edit of docChange.edits) { - if ("snippet" in edit) { - documentUris.push(Uri.parse(docChange.textDocument.uri).toString()); - snippetEdits.push(new SnippetTextEdit(client.protocol2CodeConverter.asRange((edit as any).range), new SnippetString((edit as any).snippet.value))); - } + return client.sendRequest(CodeActionResolveRequest.type, client.code2ProtocolConverter.asCodeActionSync(item), token).then(async (result) => { + if (token.isCancellationRequested) { + return item; + } + const docChanges = result.edit !== undefined ? result.edit.documentChanges : undefined; + if (docChanges !== undefined) { + for (const docChange of docChanges) { + if ("textDocument" in docChange) { + for (const edit of docChange.edits) { + if ("snippet" in edit) { + documentUris.push(Uri.parse(docChange.textDocument.uri).toString()); + snippetEdits.push(new SnippetTextEdit(client.protocol2CodeConverter.asRange((edit as any).range), new SnippetString((edit as any).snippet.value))); } } } - const codeAction = await client.protocol2CodeConverter.asCodeAction(result, token); - const docEdits = codeAction.edit !== undefined? codeAction.edit.entries() : []; - for (const docEdit of docEdits) { - const uri = docEdit[0]; - if (documentUris.includes(uri.toString())) { - const editList = []; - for (const edit of docEdit[1]) { - let isSnippet = false; - snippetEdits.forEach((snippet, index) => { - if (edit.range.isEqual(snippet.range) && documentUris[index] === uri.toString()) { - editList.push(snippet); - isSnippet = true; - } - }); - if (!isSnippet) { - editList.push(edit); + } + const codeAction = await client.protocol2CodeConverter.asCodeAction(result, token); + const docEdits = codeAction.edit !== undefined? codeAction.edit.entries() : []; + for (const docEdit of docEdits) { + const uri = docEdit[0]; + if (documentUris.includes(uri.toString())) { + const editList = []; + for (const edit of docEdit[1]) { + let isSnippet = false; + snippetEdits.forEach((snippet, index) => { + if (edit.range.isEqual(snippet.range) && documentUris[index] === uri.toString()) { + editList.push(snippet); + isSnippet = true; } + }); + if (!isSnippet) { + editList.push(edit); } - codeAction.edit.set(uri, null); - codeAction.edit.set(uri, editList); } + codeAction.edit.set(uri, null); + codeAction.edit.set(uri, editList); } - return codeAction; } - return await client.protocol2CodeConverter.asCodeAction(result, token); - }, (error) => { - return client.handleFailedRequest(CodeActionResolveRequest.type, token, error, item); - }); - }; - return resolveCodeAction(item, token); + return codeAction; + } + return await client.protocol2CodeConverter.asCodeAction(result, token); + }, (error) => { + return client.handleFailedRequest(CodeActionResolveRequest.type, token, error, item); + }); }, + + provideReferences: async(document, position, options, token, next): Promise => { + // Override includeDeclaration from VS Code by allowing it to be configured + options.includeDeclaration = getJavaConfiguration().get('references.includeDeclarations'); + return await next(document, position, options, token); + } }, revealOutputChannelOn: RevealOutputChannelOn.Never, errorHandler: new ClientErrorHandler(extensionName),