Skip to content

Commit edb71b2

Browse files
committed
Added VM Options config for notebooks, fixed enable preview failing with EA versions bug and added logger for knowing with which options the kernel is being launched
added Notebook config tests for vm options, updated description label for vm options, updated config values flow so that they are set to default if nothing is sent by lsp client
1 parent bf694c0 commit edb71b2

File tree

8 files changed

+135
-13
lines changed

8 files changed

+135
-13
lines changed

nbcode/notebooks/src/org/netbeans/modules/nbcode/java/notebook/NotebookConfigs.java

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2025, Oracle and/or its affiliates.
2+
* Copyright (c) 2025-2026, Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,12 +19,14 @@
1919
import com.google.gson.JsonObject;
2020
import java.io.File;
2121
import java.util.ArrayList;
22+
import java.util.Collections;
2223
import java.util.List;
2324
import java.util.concurrent.CompletableFuture;
2425
import java.util.logging.Level;
2526
import java.util.logging.Logger;
2627
import org.eclipse.lsp4j.ConfigurationItem;
2728
import org.eclipse.lsp4j.ConfigurationParams;
29+
import org.netbeans.api.annotations.common.NonNull;
2830
import org.netbeans.modules.java.lsp.server.protocol.NbCodeLanguageClient;
2931

3032
/**
@@ -39,12 +41,14 @@ public class NotebookConfigs {
3941
"notebook.addmodules",
4042
"notebook.enablePreview",
4143
"notebook.implicitImports",
42-
"notebook.projects.mapping"};
44+
"notebook.projects.mapping",
45+
"notebook.vmOptions"};
4346
private volatile String classPath = null;
4447
private volatile String modulePath = null;
4548
private volatile String addModules = null;
4649
private volatile boolean enablePreview = false;
4750
private volatile JsonObject notebookProjectMapping = new JsonObject();
51+
private volatile List<String> notebookVmOptions = Collections.emptyList();
4852
private volatile List<String> implicitImports = null;
4953
private volatile CompletableFuture<Void> initialized;
5054

@@ -75,6 +79,11 @@ public List<String> getImplicitImports() {
7579
public JsonObject getNotebookProjectMapping() {
7680
return notebookProjectMapping;
7781
}
82+
83+
@NonNull
84+
public List<String> getNotebookVmOptions() {
85+
return notebookVmOptions;
86+
}
7887

7988
private NotebookConfigs() {
8089

@@ -119,31 +128,50 @@ private CompletableFuture<Void> initializeConfigs() {
119128
JsonArray classPathConfig = NotebookUtils.getArgument(c, 0, JsonArray.class);
120129
if (classPathConfig != null) {
121130
classPath = String.join(File.pathSeparator,classPathConfig.asList().stream().map((elem) -> elem.getAsString()).toList());
131+
} else {
132+
classPath = null;
122133
}
123134

124135
JsonArray modulePathConfig = NotebookUtils.getArgument(c, 1, JsonArray.class);
125136
if (modulePathConfig != null) {
126137
modulePath = String.join(File.pathSeparator,modulePathConfig.asList().stream().map((elem) -> elem.getAsString()).toList());
138+
} else {
139+
modulePath = null;
127140
}
128141

129142
JsonArray addModulesConfig = NotebookUtils.getArgument(c, 2, JsonArray.class);
130143
if (addModulesConfig != null) {
131144
addModules = String.join(",",addModulesConfig.asList().stream().map((elem) -> elem.getAsString()).toList());
145+
} else {
146+
addModules = null;
132147
}
133148

134149
Boolean enablePreviewConfig = NotebookUtils.getArgument(c, 3, Boolean.class);
135150
if (enablePreviewConfig != null) {
136151
enablePreview = enablePreviewConfig;
152+
} else {
153+
enablePreview = false;
137154
}
138155

139156
JsonArray implicitImportsConfig = NotebookUtils.getArgument(c, 4, JsonArray.class);
140157
if (implicitImportsConfig != null) {
141158
implicitImports = implicitImportsConfig.asList().stream().map((elem) -> elem.getAsString()).toList();
159+
} else {
160+
implicitImports = null;
142161
}
143162

144163
JsonObject notebookProjectMappingConfig = NotebookUtils.getArgument(c, 5, JsonObject.class);
145164
if (notebookProjectMappingConfig != null) {
146165
notebookProjectMapping = notebookProjectMappingConfig;
166+
} else {
167+
notebookProjectMapping = new JsonObject();
168+
}
169+
170+
JsonArray notebookVmOptionsConfig = NotebookUtils.getArgument(c, 6, JsonArray.class);
171+
if (notebookVmOptionsConfig != null) {
172+
notebookVmOptions = notebookVmOptionsConfig.asList().stream().map(el -> el.getAsString()).toList();
173+
} else {
174+
notebookVmOptions = Collections.emptyList();
147175
}
148176
}
149177
});
@@ -154,7 +182,8 @@ private CompletableFuture<Void> initializeConfigs() {
154182
}
155183

156184
public String getJdkVersion() {
157-
return System.getProperty("java.version").split("\\.")[0];
185+
// As per JEP-223
186+
return System.getProperty("java.specification.version");
158187
}
159188

160189
public void notebookConfigsChangeListener(JsonObject settings) {

nbcode/notebooks/src/org/netbeans/modules/nbcode/java/notebook/NotebookSessionManager.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2025, Oracle and/or its affiliates.
2+
* Copyright (c) 2025-2026, Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -100,6 +100,9 @@ private JShell jshellBuildWithProject(String notebookUri, Project prj, JshellStr
100100
.err(streamsHandler.getPrintErrStream())
101101
.in(streamsHandler.getInputStream());
102102

103+
LOG.log(Level.FINE, "Initializing Notebook kernel for {0}", notebookUri);
104+
LOG.log(Level.FINE, "Compiler options being passed: {0}", compilerOptions);
105+
LOG.log(Level.FINE, "VM Options being passed to notebook kernel: {0}", remoteOptions);
103106
if (!compilerOptions.isEmpty()) {
104107
builder.compilerOptions(compilerOptions.toArray(new String[0]))
105108
.remoteVMOptions(remoteOptions.toArray(new String[0]));
@@ -226,6 +229,10 @@ private List<String> getRemoteVmOptions(Project prj) {
226229
if (enablePreview) {
227230
remoteOptions.add(ENABLE_PREVIEW);
228231
}
232+
233+
List<String> extraVmOptions = NotebookConfigs.getInstance().getNotebookVmOptions();
234+
remoteOptions.addAll(extraVmOptions);
235+
229236
return remoteOptions;
230237
}
231238

nbcode/notebooks/test/unit/src/org/netbeans/modules/nbcode/java/notebook/NotebookConfigsTest.java

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2025, Oracle and/or its affiliates.
2+
* Copyright (c) 2025-2026 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818

1919
import com.google.gson.JsonObject;
2020
import com.google.gson.JsonArray;
21+
import com.google.gson.JsonElement;
2122
import com.google.gson.JsonPrimitive;
2223
import java.io.File;
2324
import java.util.ArrayList;
@@ -37,11 +38,6 @@
3738
2.Missing keys
3839
*/
3940

40-
/*
41-
Version 1 21/08/25
42-
Version 2 25/09/25 Inline with frontend sending arrays for CP,MP,Add modules
43-
*/
44-
4541
/**
4642
* Mock LSP Client sending sample configurations
4743
* Verifies that the NotebookConfigs class
@@ -59,6 +55,7 @@ public class NotebookConfigsTest {
5955
private static final String ADD_MODULES_KEY = "jdk.notebook.addmodules";
6056
private static final String ENABLE_PREVIEW_KEY = "jdk.notebook.enablePreview";
6157
private static final String MODULEPATH_KEY = "jdk.notebook.modulepath";
58+
private static final String VM_OPTIONS_KEY = "jdk.notebook.vmOptions";
6259

6360
public NotebookConfigsTest() {
6461
}
@@ -173,26 +170,105 @@ public void testGetImplicitImports() {
173170
fail("Configuration initialization failed");
174171
}
175172
}
173+
174+
/**
175+
* Test of getNotebookVmOptions method, of class NotebookConfigs.
176+
*/
177+
@Test
178+
public void testGetNotebookVmOptions() {
179+
System.out.println("getNotebookVmOptions");
180+
try {
181+
initialized.get(5, TimeUnit.SECONDS);
182+
183+
List<String> expResult = configsObj.get(VM_OPTIONS_KEY)
184+
.getAsJsonArray()
185+
.asList()
186+
.stream()
187+
.map(elem -> elem.getAsString())
188+
.toList();
189+
190+
List<String> result = instance.getNotebookVmOptions();
176191

192+
assertEquals(expResult, result);
193+
} catch (Exception ex) {
194+
fail("Configuration initialization failed");
195+
}
196+
}
197+
198+
/**
199+
* Test of getNotebookVmOptions method when the configuration key is
200+
* missing. Verifies that the system handles a null/missing key gracefully
201+
* (likely returning an empty list).
202+
*/
203+
@Test
204+
public void testGetNotebookVmOptionsWhenMissing() {
205+
try {
206+
updateConfigValue(VM_OPTIONS_KEY, null);
207+
List<String> result = instance.getNotebookVmOptions();
208+
assertNotNull("Result should not be null even if key is missing", result);
209+
assertTrue("Result should be empty when key is missing", result.isEmpty());
210+
211+
} catch (Exception ex) {
212+
fail("Failed to handle missing VM_OPTIONS_KEY: " + ex.getMessage());
213+
}
214+
}
215+
216+
/**
217+
* Test of getNotebookVmOptions with quoted spaces.
218+
* Verifies that options containing spaces (like directory paths) are preserved.
219+
*/
220+
@Test
221+
public void testGetNotebookVmOptionsWithQuotedSpaces() {
222+
try {
223+
String quotedOption = "\"-Djava.io.tmpdir=C:\\Temp Folder\\java\"";
224+
225+
JsonArray vmOptions = new JsonArray();
226+
vmOptions.add(new JsonPrimitive(quotedOption));
227+
updateConfigValue(VM_OPTIONS_KEY, vmOptions);
228+
List<String> result = instance.getNotebookVmOptions();
229+
230+
assertTrue("Result should contain the quoted option", result.contains(quotedOption));
231+
assertEquals("Should have exactly 1 option", 1, result.size());
232+
233+
} catch (Exception ex) {
234+
fail("Configuration with quoted spaces failed");
235+
}
236+
}
237+
177238
private void setConfigObject() {
178239
JsonArray imports = new JsonArray();
179240
imports.add(new JsonPrimitive("java.math.*"));
180241
imports.add(new JsonPrimitive("javafx.scene.control.*"));
181242
configsObj.add(IMPLICIT_IMPORTS_KEY, imports);
243+
182244
JsonArray classpath = new JsonArray();
183245
classpath.add(new JsonPrimitive(
184246
"path/to/javafx-sdk-24.0.1/lib/javafx.base.jar"));
185247
configsObj.add(CLASSPATH_KEY, classpath);
248+
186249
JsonArray modulepath = new JsonArray();
187250
modulepath.add(new JsonPrimitive("/path/to/javafx-sdk/lib"));
188251
configsObj.add(MODULEPATH_KEY, modulepath);
189252
configsObj.add(ENABLE_PREVIEW_KEY, new JsonPrimitive(false));
253+
190254
JsonArray addModules = new JsonArray();
191255
addModules.add(new JsonPrimitive("javafx.controls"));
192256
addModules.add(new JsonPrimitive("javafx.graphics"));
193257
configsObj.add(ADD_MODULES_KEY, addModules);
258+
259+
JsonArray vmOptions = new JsonArray();
260+
vmOptions.add(new JsonPrimitive("--add-opens=java.base/java.lang=ALL-UNNAMED"));
261+
vmOptions.add(new JsonPrimitive("--add-opens=java.base/java.util=ALL-UNNAMED"));
262+
vmOptions.add(new JsonPrimitive("-Xmx2G"));
263+
configsObj.add(VM_OPTIONS_KEY, vmOptions);
194264

195265
}
266+
267+
private void updateConfigValue(String key, JsonElement value){
268+
configsObj.add(key, value);
269+
instance.initConfigs();
270+
instance.getInitialized();
271+
}
196272

197273
private class MockNbClientConfigs extends MockNbClient {
198274

vscode/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,11 @@
300300
"default": {},
301301
"description": "%jdk.notebook.projects.mapping.description%"
302302
},
303+
"jdk.notebook.vmOptions": {
304+
"type": "array",
305+
"default": [],
306+
"description": "%jdk.notebook.vmOptions.description%"
307+
},
303308
"jdk.telemetry.enabled": {
304309
"type": "boolean",
305310
"description": "%jdk.configuration.telemetry.enabled.description%",

vscode/package.nls.ja.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
"jdk.notebook.implicitImports.description": "Javaノートブックで暗黙的にインポートする要素のリスト。空のときのデフォルトはjava.util、java.ioおよびjava.mathパッケージのスター・インポート。",
7979
"jdk.notebook.implicitImports.markdownDescription": "Javaノートブックで暗黙的にインポートする要素のリスト。空のときのデフォルトは`java.util`、`java.io`および`java.math`パッケージのスター・インポート。",
8080
"jdk.notebook.projects.mapping.description": "Javaノートブック・パスの、コンテキストを提供するプロジェクトのパスへのマッピング。",
81+
"jdk.configuration.notebook.vmOptions.description": "The specific Java VM options for use in Java notebooks. These options are added in addition to the project configuration, including class-path, module-path, preview features, and added modules.",
8182
"jdk.configuration.java.completion.commit.chars": "コード補完の提案の受入れをトリガーする文字を指定します。たとえば、ピリオド(.)を入力したときに提案を受け入れるには、これを[\".\"]に設定します",
8283
"jdk.initialConfigurations.launchJavaApp.name": "Javaアプリケーションの起動",
8384
"jdk.configurationSnippets.name": "Javaアプリケーションの起動",

vscode/package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
"jdk.notebook.implicitImports.description": "List of elements to implicitly import in Java notebooks. Defaults to star-imports of java.util, java.io and java.math packages, when empty.",
7979
"jdk.notebook.implicitImports.markdownDescription": "List of elements to implicitly import in Java notebooks. Defaults to star-imports of `java.util`, `java.io` and `java.math` packages, when empty.",
8080
"jdk.notebook.projects.mapping.description": "Mapping of Java notebook paths to the path of the project that provides it context.",
81+
"jdk.configuration.notebook.vmOptions.description": "The specific Java VM options for use in Java notebooks. These options are added in addition to the project configuration, including class-path, module-path, preview features, and added modules.",
8182
"jdk.configuration.java.completion.commit.chars": "Specifies the characters that trigger accepting a code completion suggestion. For example, to accept suggestions when typing a dot (.), set this to [\".\"]",
8283
"jdk.initialConfigurations.launchJavaApp.name": "Launch Java App",
8384
"jdk.configurationSnippets.name": "Launch Java App",

vscode/package.nls.zh-cn.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
"jdk.notebook.implicitImports.description": "要在 Java 记事本中隐式导入的元素列表。为空时,默认为 java.util、java.io 和 java.math 程序包的星型导入。",
7979
"jdk.notebook.implicitImports.markdownDescription": "要在 Java 记事本中隐式导入的元素列表。为空时,默认为 `java.util`、`java.io` 和 `java.math` 程序包的星型导入。",
8080
"jdk.notebook.projects.mapping.description": "将 Java 记事本路径映射到提供记事本上下文的项目的路径。",
81+
"jdk.configuration.notebook.vmOptions.description": "The specific Java VM options for use in Java notebooks. These options are added in addition to the project configuration, including class-path, module-path, preview features, and added modules.",
8182
"jdk.configuration.java.completion.commit.chars": "指定用于触发接受代码补全建议的字符。例如,要在键入点 (.) 时接受建议,请将该字符设为 [\".\"]",
8283
"jdk.initialConfigurations.launchJavaApp.name": "启动 Java 应用程序",
8384
"jdk.configurationSnippets.name": "启动 Java 应用程序",

vscode/src/configurations/configuration.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2023-2024, Oracle and/or its affiliates.
2+
Copyright (c) 2023-2026, Oracle and/or its affiliates.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -36,8 +36,9 @@ export const configKeys = {
3636
notebookAddModules: "notebook.addmodules",
3737
notebookEnablePreview: "notebook.enablePreview",
3838
notebookImplicitImports: "notebook.implicitImports",
39-
telemetryEnabled: 'telemetry.enabled',
40-
notebookProjectMapping: "notebook.projects.mapping"
39+
notebookProjectMapping: "notebook.projects.mapping",
40+
notebookVmOptions: "notebook.vmOptions",
41+
telemetryEnabled: 'telemetry.enabled'
4142
};
4243

4344
export const builtInConfigKeys = {
@@ -56,6 +57,7 @@ export const userConfigsListened: string[] = [
5657
appendPrefixToCommand(configKeys.notebookEnablePreview),
5758
appendPrefixToCommand(configKeys.notebookImplicitImports),
5859
appendPrefixToCommand(configKeys.notebookProjectMapping),
60+
appendPrefixToCommand(configKeys.notebookVmOptions),
5961
builtInConfigKeys.vscodeTheme,
6062
];
6163

0 commit comments

Comments
 (0)