Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 26 additions & 30 deletions BUILD.MD
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

## Prerequisities

- JDK, version 17 or later
- JDK, version 21 or later
- Ant, latest version
- Maven, latest version
- node.js, latest LTS (to build VSIX)
Expand All @@ -33,7 +33,8 @@

```bash
$ git clone --recurse-submodules https://github.com/apache/netbeans-vscode.git
$ cd netbeans-vscode/
$ cd netbeans-vscode
netbeans-vscode$ git submodules update --init
```

## Building
Expand All @@ -44,7 +45,8 @@ To build the VS Code extension invoke:
netbeans-vscode$ ant build-netbeans
netbeans-vscode$ ant build-vscode-ext
```
The resulting extension is then in the `build` directory, with the `.vsix` extension.
The resulting VSCode extension is then generated in the `build` directory -
a file with the `.vsix` extension.
The typical file name is `apache-netbeans-java-0.1.0.vsix` - the version can be
changed by using the `-Dvsix.version=x.y.z` property - that's what
[continuous integration server](https://ci-builds.apache.org/job/Netbeans/job/netbeans-vscode/)
Expand Down Expand Up @@ -122,51 +124,40 @@ vscode$ code --extensionDevelopmentPath=`pwd` path_to_project
Or you can open the `vscode` folder in `code` directly and use **F5** to
debug the extension's *typescript code*.

To debug the *Java code*, launch the NetBeans part of the VS Code system first
and specify suitable debug arguments to start _standalone NBLS_ instance:
To debug the *Java code*, use following prepared script to launch `code` with
necessary arguments:

```bash
vscode$ npm run nbcode -- --jdkhome /jdk -J-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000
vscode$ npm run nbcode
```

To add extra modules while debugging the NetBeans part
```bash
vscode$ npm run nbcode -- -J-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000 -J-Dnetbeans.extra.dirs=/path/to/extension
```

Connect to the process with Java debugger, setup all breakpoints. Then launch
the VS Code extension (which connects to the already running _standalone NBLS_ Java process):

The script needs to have `code` and JDK available on classpath. It prints
out the command it attempts to invoke. One can either copy the command and
alter it, when necessary, but one can also provide extra arguments after `--`.
For example to add extra modules while debugging the NetBeans part
```bash
vscode$ code --extensionDevelopmentPath=`pwd` path_to_the_maven_project
vscode$ npm run nbcode -- -J-Dnetbeans.extra.dirs=/path/to/extension
```

To start from a clean state, following
The JPDA protocol listens on port 8000. Connect to the process with Java debugger,
setup all breakpoints. To start from a clean state the following
[CLI options](https://code.visualstudio.com/docs/editor/command-line)
maybe of an interest:
are being passed to the `code` by default:
- `--user-data-dir` - clean any user settings with this option
- `--extensions-dir` - avoid 3rd party extensions using this option

**Important note**: when `--user-data-dir` is used, the _standalone NBLS_ must be start as
```bash
vscode$ nbcode_userdir=/the-code-user-data-dir npm run nbcode -- --jdkhome /jdk -J-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000
```
So that the vscode can connect to the _standalone NBLS_ instance.
The script also instructs the system to print messages (stderr, out) to the console
by adding `-J-Dnetbeans.logger.console=true` to the npm commandline.
This has the same effect as `netbeans.verbose = true` settings in the vscode.

<!--
### NBLS userdir locations

The default userdir location is inside the **global** vscode settings location:
- on Linux: `~/.config/Code/User/globalStorage/asf.apache-netbeans-java/userdir
- on MacOS X: ~/Library/Application Support/Code/User/globalStorage/asf.apache-netbeans-java/userdir

When the environment variable `nbcode_userdir` (to e.g. `/tmp/foo`) is set when starting vscode or nbcode (npm run nbcode), the userdir will point to `/tmp/foo/userdir`.

### Debug output
_Standalone NBLS_ can be instructed to print messages (stderr, out) to the console: add `-J-Dnetbeans.logger.console=true` to the npm commandline. This has the same effect as `netbeans.verbose = true` settings in the vscode.

### LSP protocol tracing
Messages from the LSP protocol can be displayed in vscode by setting `java.trace.server = verbose` setting in vscode JSON settings. Sometimes it may be needed to record LSP requests and responses in the debug output log stream from the Apache NetBeans language server so that requests are properly ordered with logs from executed actions. This can be enabled on language server startup by adding `-J-Dorg.netbeans.modules.java.lsp.server.lsptrace.level=FINEST`
to the NBLS commandline.

### Debugging separately from global NBLS
By default the extension uses **global** userdir of the **global** vscode instance and uses NBLS data in there. In case this is not desired, the `launch.json` must be changed:
```
Expand All @@ -179,3 +170,8 @@ When using _standalone NBLS_ at the same time, the NBLS must be started as
vscode$ user_data_dir=/path/to/development/area npm run nbcode -- --jdkhome /jdk -J-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000
```
This way the NBLS will use a separate config/cache directory and will not interfere with the default / global installation.
-->

### LSP protocol tracing
Messages from the LSP protocol can be displayed in vscode by setting `java.trace.server = verbose` setting in vscode JSON settings. Sometimes it may be needed to record LSP requests and responses in the debug output log stream from the Apache NetBeans language server so that requests are properly ordered with logs from executed actions. This can be enabled on language server startup by adding `-J-Dorg.netbeans.modules.java.lsp.server.lsptrace.level=FINEST`
to the NBLS commandline.
2 changes: 1 addition & 1 deletion vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1516,7 +1516,7 @@
"compile": "tsc -p ./ && node ./esbuild.js",
"watch": "tsc -watch -p ./ | node ./esbuild.js --watch",
"test": "node ./out/test/runTest.js",
"nbcode": "node ./out/nbcode.js",
"nbcode": "npm run compile && node ./out/nbcode.js",
"nbjavac": "node ./out/nbcode.js -J-Dnetbeans.close=true --modules --install .*nbjavac.*",
"apisupport": "node ./out/nbcode.js -J-Dnetbeans.close=true --modules --install '(org.netbeans.libs.xerces|org.netbeans.modules.editor.structure|org.netbeans.modules.xml|org.netbeans.modules.xml.axi|org.netbeans.modules.xml.retriever|org.netbeans.modules.xml.schema.model|org.netbeans.modules.xml.tax|org.netbeans.modules.xml.text|org.netbeans.modules.ant.browsetask|.*apisupport.*|org.netbeans.modules.debugger.jpda.ant)' && node ./out/nbcode.js -J-Dnetbeans.close=true --modules --enable .*apisupport.ant"
},
Expand Down
79 changes: 44 additions & 35 deletions vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import * as launcher from './nbcode';
import {NbTestAdapter} from './testAdapter';
import { asRanges, StatusMessageRequest, ShowStatusMessageParams, QuickPickRequest, InputBoxRequest, MutliStepInputRequest, TestProgressNotification, DebugConnector,
TextEditorDecorationCreateRequest, TextEditorDecorationSetNotification, TextEditorDecorationDisposeNotification, HtmlPageRequest, HtmlPageParams,
ExecInHtmlPageRequest, SetTextEditorDecorationParams, ProjectActionParams, UpdateConfigurationRequest, QuickPickStep, InputBoxStep, SaveDocumentsRequest, SaveDocumentRequestParams, OutputMessage, WriteOutputRequest, ShowOutputRequest, CloseOutputRequest, ResetOutputRequest
ExecInHtmlPageRequest, SetTextEditorDecorationParams, ProjectActionParams, UpdateConfigurationRequest, QuickPickStep, InputBoxStep, SaveDocumentsRequest, SaveDocumentRequestParams, OutputMessage, WriteOutputRequest, ShowOutputRequest, CloseOutputRequest, ResetOutputRequest
} from './protocol';
import * as launchConfigurations from './launchConfigurations';
import { createTreeViewService, TreeViewService, TreeItemDecorator, Visualizer, CustomizableTreeDataProvider } from './explorer';
Expand All @@ -67,6 +67,7 @@ import * as sshGuide from './panels/SshGuidePanel';
import * as runImageGuide from './panels/RunImageGuidePanel';
import { shouldHideGuideFor } from './panels/guidesUtil';
import { SSHSession } from './ssh/ssh';
import { env } from 'process';

const API_VERSION : string = "1.0";
export const COMMAND_PREFIX : string = "nbls";
Expand Down Expand Up @@ -132,30 +133,37 @@ export function enableConsoleLog() {
console.log("enableConsoleLog");
}

export function findClusters(myPath : string): string[] {
let clusters = [];
export function findClusters(myPath : string, log: vscode.OutputChannel): string[] {
let clusters: string[] = [];
for (let e of vscode.extensions.all) {
if (e.extensionPath === myPath) {
continue;
}
const dir = path.join(e.extensionPath, 'nbcode');
if (!fs.existsSync(dir)) {
continue;
}
const exists = fs.readdirSync(dir);
for (let clusterName of exists) {
let clusterPath = path.join(dir, clusterName);
let clusterModules = path.join(clusterPath, 'config', 'Modules');
if (!fs.existsSync(clusterModules)) {
continue;
searchAddCluster(dir);
}
return clusters;

function searchAddCluster(rootWithClusters: string) {
if (fs.existsSync(rootWithClusters)) {
const exists = fs.readdirSync(rootWithClusters);
for (let clusterName of exists) {
let clusterPath = path.join(rootWithClusters, clusterName);
addCluster(clusterPath);
}
}
}
function addCluster(clusterPath: string): boolean {
let clusterModules = path.join(clusterPath, 'config', 'Modules');
if (fs.existsSync(clusterModules)) {
let perm = fs.statSync(clusterModules);
if (perm.isDirectory()) {
clusters.push(clusterPath);
return true;
}
}
return false;
}
return clusters;
}

// for tests only !
Expand Down Expand Up @@ -397,7 +405,7 @@ class LineBufferingPseudoterminal implements vscode.Pseudoterminal {
private closeEmitter = new vscode.EventEmitter<void>();
onDidClose?: vscode.Event<void> = this.closeEmitter.event;

private buffer: string = '';
private buffer: string = '';
private isOpen = false;
private readonly name: string;
private terminal: vscode.Terminal | undefined;
Expand Down Expand Up @@ -476,7 +484,7 @@ class LineBufferingPseudoterminal implements vscode.Pseudoterminal {
}
});
}
// Prevent 'stealing' of the focus when running tests in parallel
// Prevent 'stealing' of the focus when running tests in parallel
if (!testAdapter?.testInParallelProfileExist()) {
this.terminal.show(true);
}
Expand All @@ -494,12 +502,12 @@ class LineBufferingPseudoterminal implements vscode.Pseudoterminal {
this.instances.set(name, instance);
}
const instance = this.instances.get(name)!;
instance.show();
instance.show();
return instance;
}
}

export function activate(context: ExtensionContext): VSNetBeansAPI {
export function activate(context: ExtensionContext): VSNetBeansAPI {
const provider = new StringContentProvider();
const scheme = 'in-memory';
const providerRegistration = vscode.workspace.registerTextDocumentContentProvider(scheme, provider);
Expand All @@ -511,7 +519,7 @@ export function activate(context: ExtensionContext): VSNetBeansAPI {
if (selected == POLICIES_UPLOAD) {
await vscode.commands.executeCommand('nbls.cloud.assets.policy.upload');
return;
}
}

const content = await vscode.commands.executeCommand('nbls.cloud.assets.policy.create.local') as string;
const document = vscode.Uri.parse(`${scheme}:policies.txt?${encodeURIComponent(content)}`);
Expand All @@ -530,7 +538,7 @@ export function activate(context: ExtensionContext): VSNetBeansAPI {
return;
} else if (selected == CONFIG_TO_OKE_CM) {
await commands.executeCommand('nbls.cloud.assets.configmap.upload');
return;
return;
}
const content = await vscode.commands.executeCommand('nbls.cloud.assets.config.create.local') as string;
const document = vscode.Uri.parse(`${scheme}:application.properties?${encodeURIComponent(content)}`);
Expand Down Expand Up @@ -621,9 +629,9 @@ export function activate(context: ExtensionContext): VSNetBeansAPI {
});
}
}
let warnedJDKs : string[] = specifiedJDKWarned;
let warnedJDKs : string[] = specifiedJDKWarned;
if (!jdkOK && !warnedJDKs.includes(specifiedJDK || '')) {
const msg = specifiedJDK ?
const msg = specifiedJDK ?
`The current path to JDK "${specifiedJDK}" may be invalid. A valid JDK ${MINIMAL_JDK_VERSION}+ is required by Apache NetBeans Language Server to run.
You should configure a proper JDK for Apache NetBeans and/or other technologies. Do you want to run JDK configuration now?` :
`A valid JDK ${MINIMAL_JDK_VERSION}+ is required by Apache NetBeans Language Server to run, but none was found. You should configure a proper JDK for Apache NetBeans and/or other technologies. ` +
Expand All @@ -637,7 +645,7 @@ export function activate(context: ExtensionContext): VSNetBeansAPI {
warnedJDKs.push(specifiedJDK || '');
}
}
let currentClusters = findClusters(context.extensionPath).sort();
let currentClusters = findClusters(context.extensionPath, log).sort();
const dsSorter = (a: TextDocumentFilter, b: TextDocumentFilter) => {
return (a.language || '').localeCompare(b.language || '')
|| (a.pattern || '').localeCompare(b.pattern || '')
Expand All @@ -646,7 +654,7 @@ export function activate(context: ExtensionContext): VSNetBeansAPI {
let currentDocumentSelectors = collectDocumentSelectors().sort(dsSorter);
context.subscriptions.push(vscode.extensions.onDidChange(() => {
checkConflict();
const newClusters = findClusters(context.extensionPath).sort();
const newClusters = findClusters(context.extensionPath, log).sort();
const newDocumentSelectors = collectDocumentSelectors().sort(dsSorter);
if (newClusters.length !== currentClusters.length || newDocumentSelectors.length !== currentDocumentSelectors.length
|| newClusters.find((value, index) => value !== currentClusters[index]) || newDocumentSelectors.find((value, index) => value !== currentDocumentSelectors[index])) {
Expand Down Expand Up @@ -900,7 +908,7 @@ export function activate(context: ExtensionContext): VSNetBeansAPI {
}
class P implements vscode.DebugConfigurationProvider {
config : vscode.DebugConfiguration | undefined;

resolveDebugConfigurationWithSubstitutedVariables(folder: vscode.WorkspaceFolder | undefined, debugConfiguration: vscode.DebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult<vscode.DebugConfiguration> {
this.config = debugConfiguration;
return undefined;
Expand Down Expand Up @@ -953,15 +961,15 @@ export function activate(context: ExtensionContext): VSNetBeansAPI {
} else {
debugConfig['mainClass'] = docUri.toString();
}

if (testInParallel) {
debugConfig['testInParallel'] = testInParallel;
}
if (projects?.length) {
debugConfig['projects'] = projects;
}

const ret = await vscode.debug.startDebugging(workspaceFolder, debugConfig);
const ret = await vscode.debug.startDebugging(workspaceFolder, debugConfig);
return ret ? new Promise((resolve) => {
const listener = vscode.debug.onDidTerminateDebugSession(() => {
listener.dispose();
Expand All @@ -971,11 +979,11 @@ export function activate(context: ExtensionContext): VSNetBeansAPI {
}
};

context.subscriptions.push(commands.registerCommand(COMMAND_PREFIX + '.run.test.parallel', async (projects?) => {
context.subscriptions.push(commands.registerCommand(COMMAND_PREFIX + '.run.test.parallel', async (projects?) => {
testAdapter?.runTestsWithParallelProfile(projects);
}));

context.subscriptions.push(commands.registerCommand(COMMAND_PREFIX + '.run.test.parallel.createProfile', async (projects?) => {
context.subscriptions.push(commands.registerCommand(COMMAND_PREFIX + '.run.test.parallel.createProfile', async (projects?) => {
testAdapter?.registerRunInParallelProfile(projects);
}));

Expand Down Expand Up @@ -1151,7 +1159,7 @@ export function activate(context: ExtensionContext): VSNetBeansAPI {
*/
let maintenance : Promise<void> | null;

function activateWithJDK(specifiedJDK: string | null, context: ExtensionContext, log : vscode.OutputChannel, notifyKill: boolean,
function activateWithJDK(specifiedJDK: string | null, context: ExtensionContext, log : vscode.OutputChannel, notifyKill: boolean,
clientResolve? : (x : NbLanguageClient) => void, clientReject? : (x : any) => void): void {
let oldClient = client;
let setClient : [(c : NbLanguageClient) => void, (err : any) => void];
Expand Down Expand Up @@ -1293,12 +1301,13 @@ function doActivateWithJDK(promise: Promise<NbLanguageClient>, specifiedJDK: str
}

let info = {
clusters : findClusters(context.extensionPath),
clusters : findClusters(context.extensionPath, log),
debug: env['netbeans_debug'] ? '-J-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000' : null,
extensionPath: context.extensionPath,
storagePath : userdir,
jdkHome : specifiedJDK,
verbose: beVerbose
};
};
let launchMsg = `Launching Apache NetBeans Language Server with ${specifiedJDK ? specifiedJDK : 'default system JDK'} and userdir ${userdir}`;
handleLog(log, launchMsg);
vscode.window.setStatusBarMessage(launchMsg, 2000);
Expand Down Expand Up @@ -1443,9 +1452,9 @@ function doActivateWithJDK(promise: Promise<NbLanguageClient>, specifiedJDK: str
errorHandler: {
error : function(error: Error, _message: Message, count: number): ErrorHandlerResult {
startupError = error.message;
return {
action: started ? ErrorAction.Continue : ErrorAction.Shutdown,
message: error.message
return {
action: started ? ErrorAction.Continue : ErrorAction.Shutdown,
message: error.message
};
},
closed : function(): CloseHandlerResult {
Expand Down Expand Up @@ -1514,7 +1523,7 @@ function doActivateWithJDK(promise: Promise<NbLanguageClient>, specifiedJDK: str
if (uriList.includes(uri)) {
ed.save();
continue;
}
}
if (uri.startsWith("file:///")) {
// make file:/// just file:/
uri = "file:/" + uri.substring(8);
Expand Down
Loading
Loading