diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 656e40f59..dcf9b8df1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -81,7 +81,7 @@ jobs: - name: Set Up Java uses: actions/setup-java@v4 with: - java-version: '17' + java-version: '23' distribution: 'adopt' - name: Build JDT-LS if: "${{ inputs.JDT_LS_VERSION == '' }}" diff --git a/README.md b/README.md index aeda1347f..8334a5f3b 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,10 @@ The following settings are supported: - Call Hierarchy - Workspace Symbols +New in 1.36.0 +* `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 `false`. +* `java.completion.engine`: [Experimental] Select code completion engine. Defaults to `ecj`. + 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/USAGE_DATA.md b/USAGE_DATA.md index 759e7ac56..e0d0fc53e 100644 --- a/USAGE_DATA.md +++ b/USAGE_DATA.md @@ -19,10 +19,10 @@ vscode-java has opt-in telemetry collection, provided by [vscode-redhat-telemetr * Errors relating to running the language server, such as the message & stacktrace * Whether there is a mismatch between the project's requested source level, and the JDK used for the project (eg. true) * Information about the following settings. In the case of settings that store a well defined value (eg. path/url/string), we simply collect whether the setting has been set. - * `java.settings.url`, `java.format.settings.url`, `java.quickfix.showAt`, `java.symbols.includeSourceMethodDeclarations`, `java.completion.collapseCompletionItems`, `java.completion.guessMethodArguments`, `java.completion.postfix.enabled`, `java.cleanup.actionsOnSave`, `java.sharedIndexes.enabled`, `java.inlayHints.parameterNames.enabled`, `java.server.launchMode`, `java.autobuild.enabled` + * `java.settings.url`, `java.format.settings.url`, `java.quickfix.showAt`, `java.symbols.includeSourceMethodDeclarations`, `java.completion.collapseCompletionItems`, `java.completion.guessMethodArguments`, `java.completion.postfix.enabled`, `java.cleanup.actionsOnSave`, `java.sharedIndexes.enabled`, `java.inlayHints.parameterNames.enabled`, `java.server.launchMode`, `java.autobuild.enabled`, `java.jdt.ls.javac.enabled` * The extension name and the choice made when a recommendation to install a 3rd party extension is proposed * The name of Java commands being manually executed, and any resulting errors - * The number of results (eg. 20), whether an error occured (eg. false), and duration (in milliseconds) when code assist is activated + * The number of results (eg. 20), whether an error occured (eg. false), engine type (eg. 'ecj', 'dom') and duration (in milliseconds) when code assist is activated * Whether the language server ran out of memory and the maximum allocated memory at which that occured (eg. 200m) ## What's included in the general telemetry data diff --git a/package.json b/package.json index df613ab80..8c5bcc29a 100644 --- a/package.json +++ b/package.json @@ -409,6 +409,17 @@ "scope": "window", "order": 90 }, + "java.jdt.ls.javac.enabled": { + "type": "string", + "enum": [ + "on", + "off" + ], + "default": "off", + "markdownDescription": "[Experimental] Specify whether to enable Javac-based compilation in the language server. Requires running this extension with Java 23", + "scope": "window", + "order": 95 + }, "java.trace.server": { "type": "string", "enum": [ @@ -1009,6 +1020,21 @@ "scope": "window", "order": 10 }, + "java.completion.engine": { + "type": "string", + "default": "ecj", + "description": "[Experimental] Select code completion engine", + "scope": "window", + "enum": [ + "ecj", + "dom" + ], + "markdownEnumDescriptions": [ + "Use ECJ-based code completion engine (default)", + "Use (highly experimental) JDT DOM-based code completion engine (requires `java.jdt.ls.javac.enabled` to be `on`)" + ], + "order": 1000 + }, "java.completion.postfix.enabled": { "type": "boolean", "default": true, @@ -1939,4 +1965,4 @@ }, "segmentWriteKey": "Y7Y5Xk8dKEhVZHTmAkFZkqgdN4d7c4lt", "segmentWriteKeyDebug": "BflPll7uuKOCm3y0g7JpfXLVBVFBivDE" -} +} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 39d5a32d8..b0db04d5f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1203,6 +1203,7 @@ export function registerCodeCompletionTelemetryListener() { resultLength: traceEvent.resultLength || 0, error: !!traceEvent.error, fromSyntaxServer: !!traceEvent.fromSyntaxServer, + engine: getJavaConfiguration().get('completion.engine'), }; return Telemetry.sendTelemetry(Telemetry.COMPLETION_EVENT, props); } diff --git a/src/javaServerStarter.ts b/src/javaServerStarter.ts index b8886d05c..4aa52d2c0 100644 --- a/src/javaServerStarter.ts +++ b/src/javaServerStarter.ts @@ -104,7 +104,40 @@ function prepareParams(requirements: RequirementsData, workspacePath, context: E // See https://github.com/redhat-developer/vscode-java/issues/2264 // It requires the internal API sun.nio.fs.WindowsFileAttributes.isDirectoryLink() to check if a Windows directory is symlink. '--add-opens', - 'java.base/sun.nio.fs=ALL-UNNAMED'); + 'java.base/sun.nio.fs=ALL-UNNAMED' + ); + + const javacEnabled = 'on' === getJavaConfiguration().get('jdt.ls.javac.enabled'); + if (javacEnabled) { + // Javac flags + params.push( + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED', + '--add-opens', + 'jdk.javadoc/jdk.javadoc.internal.doclets.formats.html.taglets.snippet=ALL-UNNAMED --add-opens jdk.javadoc/jdk.javadoc.internal.doclets.formats.html.taglets=ALL-UNNAMED', + '-DICompilationUnitResolver=org.eclipse.jdt.core.dom.JavacCompilationUnitResolver', + '-DCompilationUnit.DOM_BASED_OPERATIONS=true', + '-DAbstractImageBuilder.compilerFactory=org.eclipse.jdt.internal.javac.JavacCompilerFactory' + ); + + if('dom' === getJavaConfiguration().get('completion.engine')){ + params.push('-DCompilationUnit.codeComplete.DOM_BASED_OPERATIONS=true'); + }; + } params.push('-Declipse.application=org.eclipse.jdt.ls.core.id1', '-Dosgi.bundles.defaultStartLevel=4', diff --git a/src/requirements.ts b/src/requirements.ts index b753f2200..b30dfe812 100644 --- a/src/requirements.ts +++ b/src/requirements.ts @@ -9,8 +9,8 @@ import { Commands } from './commands'; import { logger } from './log'; import { checkJavaPreferences } from './settings'; import { listJdks, sortJdksBySource, sortJdksByVersion } from './jdkUtils'; +import { getJavaConfiguration } from './utils'; -const REQUIRED_JDK_VERSION = 17; /* eslint-disable @typescript-eslint/naming-convention */ export interface RequirementsData { tooling_jre: string; @@ -41,6 +41,7 @@ export async function resolveRequirements(context: ExtensionContext): Promise