sdedic commented on code in PR #7555:
URL: https://github.com/apache/netbeans/pull/7555#discussion_r1669981023


##########
java/java.lsp.server/vscode/src/jdk/validation/extensionUtils.ts:
##########
@@ -0,0 +1,28 @@
+import * as vscode from 'vscode';
+
+const RH_EXTENSION_ID = 'redhat.java';
+const EXTENSION_NBLS_ID = 'asf.apache-netbeans-java';
+const TIMEOUT_COMMAND_GET_PROJECT_INFO = 60; // wait for NBLS & projectInfo up 
to 60 seconds
+
+export function isRHExtensionActive(): boolean {
+    const rh = vscode.extensions.getExtension(RH_EXTENSION_ID);
+    return rh ? true : false;

Review Comment:
   The function seems to be intended to determine whether the extension is 
**active** for the workspace. If so, then check `rh.isActive` property value.



##########
java/java.lsp.server/vscode/src/jdk/validation/project.ts:
##########
@@ -0,0 +1,171 @@
+import * as xml2js from 'xml2js';
+import * as fs from 'fs';
+import * as path from 'path';
+import * as vscode from 'vscode';
+import * as os from 'os';
+import { normalizeJavaVersion } from './javaUtil';
+
+const GET_PROJECT_INFO = 'nbls.project.info';
+const GRADLE_TARGET_COMPATIBILITY_REGEX = 
/targetCompatibility\s*=\s*(?:JavaVersion\.toVersion\(['"](\d+(\.\d+)?)['"]\)|['"](\d+(\.\d+)?)['"])/
+const GRADLE_SOURCE_COMPATIBILITY_REGEX = 
/sourceCompatibility\s*=\s*(?:JavaVersion\.toVersion\(['"](\d+(\.\d+)?)['"]\)|['"](\d+(\.\d+)?)['"])/
+
+export enum BuildSystemType {
+    MAVEN = 'Maven',
+    GRADLE = 'Gradle',
+    UNKNOWN = 'Unknown'
+}
+
+export async function getProjectFrom(projectUri: vscode.Uri): Promise<Project 
| undefined> {
+    const projectInfos: any[] = await 
vscode.commands.executeCommand(GET_PROJECT_INFO, projectUri.toString(), { 
projectStructure: true });
+    if (projectInfos?.length && projectInfos[0]) {
+        const projectDirectory = projectInfos[0].projectDirectory.toString();
+        const buildSystem: BuildSystemType = 
resolveBuildSystemType(projectUri, projectInfos[0].projectType);
+
+        switch (buildSystem) {
+            case BuildSystemType.MAVEN:
+                const mavenSubprojects: Project[] = projectInfos[0].subprojects
+                    .map((subproject: string) => new MavenProject(subproject, 
[]))
+                return new MavenProject(projectDirectory, mavenSubprojects);
+            case BuildSystemType.GRADLE:
+                const gradleSubprojects: Project[] = 
projectInfos[0].subprojects
+                    .map((subproject: string) => new GradleProject(subproject, 
[]))
+                return new GradleProject(projectDirectory, gradleSubprojects);
+            default:
+                break;
+        }
+    }
+    return Promise.resolve(undefined);
+}
+
+function resolveBuildSystemType(uri: vscode.Uri, projectType?: string): 
BuildSystemType {
+    if (projectType?.includes('gradle')) {
+        return BuildSystemType.GRADLE;
+    }
+    if (projectType?.includes('maven')) {
+        return BuildSystemType.MAVEN;
+    }
+    if (fs.existsSync(path.join(uri.fsPath, 'build.gradle'))) {
+        return BuildSystemType.GRADLE;
+    }
+    if (fs.existsSync(path.join(uri.fsPath, 'pom.xml'))) {
+        return BuildSystemType.MAVEN;
+    }
+    return BuildSystemType.UNKNOWN;
+}
+
+export abstract class Project {
+
+    readonly directory: string;
+    readonly subprojects: Project[];
+
+    constructor(directory: string, subprojects: any[]) {
+        this.directory = directory.replace('file:/', '');
+        this.subprojects = subprojects;
+    }
+
+    // Whether the project contains subprojects
+    containsSubprojects(): boolean {
+        return this.subprojects.length > 0;
+    }
+
+    async getJavaVersion(): Promise<number | undefined> {
+        if (!this.containsSubprojects()) {
+            return this.extractJavaVersion();
+        }
+
+        let maxJavaVersion: number | undefined;
+
+        for (const subproject of this.subprojects) {
+            const subInfos: any[] = await 
vscode.commands.executeCommand(GET_PROJECT_INFO, 
`file:/${subproject.directory}`);
+            if (subInfos?.length && subInfos[0]) {
+                const javaVersion = subproject.extractJavaVersion();
+
+                if (!maxJavaVersion || (javaVersion && javaVersion > 
maxJavaVersion)) {
+                    maxJavaVersion = javaVersion;
+                }
+            }
+        }
+        return maxJavaVersion;
+    }
+
+    // Extracts project java version
+    protected abstract extractJavaVersion(): number | undefined
+}
+
+export class MavenProject extends Project {
+
+    constructor(directory: string, subprojects: any[]) {
+        super(directory, subprojects);
+    }
+
+    extractJavaVersion(): number | undefined {
+        const buildscript = path.resolve(this.directory, 'pom.xml');
+        let version: string | undefined;
+        if (fs.existsSync(buildscript)) {
+            xml2js.parseString(fs.readFileSync(buildscript)?.toString() || '', 
(err, result) => {

Review Comment:
   Note: according to the documentation, `xml2js` is now synchronous by 
default, but docs does recommend not to rely on the default behaviour. I'd 
recommend to use `await new xml2js.Parser(...).parseStringSync()` and possibly 
catch/log error results; or at least specifyc `async: false` explicitly to 
Parser options.



##########
java/java.lsp.server/vscode/src/jdk/validation/javaUtil.ts:
##########
@@ -0,0 +1,63 @@
+import * as fs from 'fs';
+import * as path from 'path';
+import * as cp from 'child_process';
+
+const JAVA_VERSION_REGEX = /version\s+"(\S+)"/;
+
+function findExecutable(program: string, home: string): string | undefined {
+    if (home) {
+        let executablePath = path.join(home, 'bin', program);
+        if (process.platform === 'win32') {
+            if (fs.existsSync(executablePath + '.cmd')) {
+                return executablePath + '.cmd';
+            }
+            if (fs.existsSync(executablePath + '.exe')) {
+                return executablePath + '.exe';
+            }
+        } else if (fs.existsSync(executablePath)) {
+            return executablePath;
+        }
+    }
+    return undefined;
+}
+
+export function normalizeJavaVersion(version: string): string {
+    return version.startsWith("1.") ? version.substring(2) : version;
+}
+
+export async function getJavaVersion(homeFolder: string): Promise<string | 
undefined> {
+    return new Promise<string | undefined>(resolve => {
+        if (homeFolder && fs.existsSync(homeFolder)) {
+            const executable: string | undefined = findExecutable('java', 
homeFolder);
+            if (executable) {
+                cp.execFile(executable, ['-version'], { encoding: 'utf8' }, 
(_error, _stdout, stderr) => {
+                    if (stderr) {
+                        let javaVersion: string | undefined;
+                        stderr.split('\n').forEach((line: string) => {
+                            const javaInfo: string[] | null = 
line.match(JAVA_VERSION_REGEX);
+                            if (javaInfo && javaInfo.length > 1) {
+                                javaVersion = javaInfo[1];
+                            }
+                        });
+                        if (javaVersion) {
+                            let majorVersion = 
normalizeJavaVersion(javaVersion);
+                            let i = majorVersion.indexOf('.');
+                            if (i > -1) {
+                                majorVersion = majorVersion.slice(0, i);
+                            }
+                            resolve(majorVersion);
+                        } else {
+                            resolve(undefined);

Review Comment:
   Nitpick: Multiple `resolve(undefined)` can be simplified to  just two 
`resolve(undefined)` unconditionally at the end of lambda + promise body.



##########
java/java.lsp.server/vscode/src/extension.ts:
##########
@@ -184,6 +185,7 @@ function findJDK(onChange: (path : string | null) => void): 
void {
     }
 
     let currentJdk = find();
+    validateJDKCompatibility(currentJdk);

Review Comment:
   note -- there's a pending PR #7497 that introduces `projectJDK`. Depending 
on which one will merge first, the other PR should change to validate the 
`projectJDK`



##########
java/java.lsp.server/vscode/src/jdk/validation/project.ts:
##########
@@ -0,0 +1,171 @@
+import * as xml2js from 'xml2js';
+import * as fs from 'fs';
+import * as path from 'path';
+import * as vscode from 'vscode';
+import * as os from 'os';
+import { normalizeJavaVersion } from './javaUtil';
+
+const GET_PROJECT_INFO = 'nbls.project.info';
+const GRADLE_TARGET_COMPATIBILITY_REGEX = 
/targetCompatibility\s*=\s*(?:JavaVersion\.toVersion\(['"](\d+(\.\d+)?)['"]\)|['"](\d+(\.\d+)?)['"])/
+const GRADLE_SOURCE_COMPATIBILITY_REGEX = 
/sourceCompatibility\s*=\s*(?:JavaVersion\.toVersion\(['"](\d+(\.\d+)?)['"]\)|['"](\d+(\.\d+)?)['"])/
+
+export enum BuildSystemType {
+    MAVEN = 'Maven',
+    GRADLE = 'Gradle',
+    UNKNOWN = 'Unknown'
+}
+
+export async function getProjectFrom(projectUri: vscode.Uri): Promise<Project 
| undefined> {
+    const projectInfos: any[] = await 
vscode.commands.executeCommand(GET_PROJECT_INFO, projectUri.toString(), { 
projectStructure: true });
+    if (projectInfos?.length && projectInfos[0]) {
+        const projectDirectory = projectInfos[0].projectDirectory.toString();
+        const buildSystem: BuildSystemType = 
resolveBuildSystemType(projectUri, projectInfos[0].projectType);
+
+        switch (buildSystem) {
+            case BuildSystemType.MAVEN:
+                const mavenSubprojects: Project[] = projectInfos[0].subprojects
+                    .map((subproject: string) => new MavenProject(subproject, 
[]))
+                return new MavenProject(projectDirectory, mavenSubprojects);
+            case BuildSystemType.GRADLE:
+                const gradleSubprojects: Project[] = 
projectInfos[0].subprojects
+                    .map((subproject: string) => new GradleProject(subproject, 
[]))
+                return new GradleProject(projectDirectory, gradleSubprojects);
+            default:
+                break;
+        }
+    }
+    return Promise.resolve(undefined);
+}
+
+function resolveBuildSystemType(uri: vscode.Uri, projectType?: string): 
BuildSystemType {
+    if (projectType?.includes('gradle')) {
+        return BuildSystemType.GRADLE;
+    }
+    if (projectType?.includes('maven')) {
+        return BuildSystemType.MAVEN;
+    }
+    if (fs.existsSync(path.join(uri.fsPath, 'build.gradle'))) {
+        return BuildSystemType.GRADLE;
+    }
+    if (fs.existsSync(path.join(uri.fsPath, 'pom.xml'))) {
+        return BuildSystemType.MAVEN;
+    }
+    return BuildSystemType.UNKNOWN;
+}
+
+export abstract class Project {
+
+    readonly directory: string;
+    readonly subprojects: Project[];
+
+    constructor(directory: string, subprojects: any[]) {
+        this.directory = directory.replace('file:/', '');
+        this.subprojects = subprojects;
+    }
+
+    // Whether the project contains subprojects
+    containsSubprojects(): boolean {
+        return this.subprojects.length > 0;
+    }
+
+    async getJavaVersion(): Promise<number | undefined> {
+        if (!this.containsSubprojects()) {
+            return this.extractJavaVersion();
+        }
+
+        let maxJavaVersion: number | undefined;
+
+        for (const subproject of this.subprojects) {
+            const subInfos: any[] = await 
vscode.commands.executeCommand(GET_PROJECT_INFO, 
`file:/${subproject.directory}`);
+            if (subInfos?.length && subInfos[0]) {
+                const javaVersion = subproject.extractJavaVersion();
+
+                if (!maxJavaVersion || (javaVersion && javaVersion > 
maxJavaVersion)) {
+                    maxJavaVersion = javaVersion;
+                }
+            }
+        }
+        return maxJavaVersion;
+    }
+
+    // Extracts project java version
+    protected abstract extractJavaVersion(): number | undefined

Review Comment:
   Please file an issue against Netbeans project, to extend `GET_PROJECT_INFO` 
(or provide an additional command) with java settings -- the 
source/target/release info is already internally available from maven/gradle 
parsing itself; just not exported to LS protocol.
   
   Note the issue # here and note this code location in that issue as well, so 
it is eventually updated when the info becomes available.



##########
java/java.lsp.server/vscode/src/jdk/validation/project.ts:
##########
@@ -0,0 +1,171 @@
+import * as xml2js from 'xml2js';
+import * as fs from 'fs';
+import * as path from 'path';
+import * as vscode from 'vscode';
+import * as os from 'os';
+import { normalizeJavaVersion } from './javaUtil';
+
+const GET_PROJECT_INFO = 'nbls.project.info';
+const GRADLE_TARGET_COMPATIBILITY_REGEX = 
/targetCompatibility\s*=\s*(?:JavaVersion\.toVersion\(['"](\d+(\.\d+)?)['"]\)|['"](\d+(\.\d+)?)['"])/
+const GRADLE_SOURCE_COMPATIBILITY_REGEX = 
/sourceCompatibility\s*=\s*(?:JavaVersion\.toVersion\(['"](\d+(\.\d+)?)['"]\)|['"](\d+(\.\d+)?)['"])/
+
+export enum BuildSystemType {
+    MAVEN = 'Maven',
+    GRADLE = 'Gradle',
+    UNKNOWN = 'Unknown'
+}
+
+export async function getProjectFrom(projectUri: vscode.Uri): Promise<Project 
| undefined> {
+    const projectInfos: any[] = await 
vscode.commands.executeCommand(GET_PROJECT_INFO, projectUri.toString(), { 
projectStructure: true });
+    if (projectInfos?.length && projectInfos[0]) {
+        const projectDirectory = projectInfos[0].projectDirectory.toString();
+        const buildSystem: BuildSystemType = 
resolveBuildSystemType(projectUri, projectInfos[0].projectType);
+
+        switch (buildSystem) {
+            case BuildSystemType.MAVEN:
+                const mavenSubprojects: Project[] = projectInfos[0].subprojects
+                    .map((subproject: string) => new MavenProject(subproject, 
[]))
+                return new MavenProject(projectDirectory, mavenSubprojects);
+            case BuildSystemType.GRADLE:
+                const gradleSubprojects: Project[] = 
projectInfos[0].subprojects
+                    .map((subproject: string) => new GradleProject(subproject, 
[]))
+                return new GradleProject(projectDirectory, gradleSubprojects);
+            default:
+                break;
+        }
+    }
+    return Promise.resolve(undefined);
+}
+
+function resolveBuildSystemType(uri: vscode.Uri, projectType?: string): 
BuildSystemType {
+    if (projectType?.includes('gradle')) {
+        return BuildSystemType.GRADLE;
+    }
+    if (projectType?.includes('maven')) {
+        return BuildSystemType.MAVEN;
+    }
+    if (fs.existsSync(path.join(uri.fsPath, 'build.gradle'))) {
+        return BuildSystemType.GRADLE;
+    }
+    if (fs.existsSync(path.join(uri.fsPath, 'pom.xml'))) {
+        return BuildSystemType.MAVEN;
+    }
+    return BuildSystemType.UNKNOWN;
+}
+
+export abstract class Project {
+
+    readonly directory: string;
+    readonly subprojects: Project[];
+
+    constructor(directory: string, subprojects: any[]) {
+        this.directory = directory.replace('file:/', '');
+        this.subprojects = subprojects;
+    }
+
+    // Whether the project contains subprojects
+    containsSubprojects(): boolean {
+        return this.subprojects.length > 0;
+    }
+
+    async getJavaVersion(): Promise<number | undefined> {
+        if (!this.containsSubprojects()) {
+            return this.extractJavaVersion();
+        }
+
+        let maxJavaVersion: number | undefined;
+
+        for (const subproject of this.subprojects) {
+            const subInfos: any[] = await 
vscode.commands.executeCommand(GET_PROJECT_INFO, 
`file:/${subproject.directory}`);

Review Comment:
   Use `vscode.Uri.file(path).toString()`



##########
java/java.lsp.server/vscode/src/jdk/validation/project.ts:
##########
@@ -0,0 +1,171 @@
+import * as xml2js from 'xml2js';
+import * as fs from 'fs';
+import * as path from 'path';
+import * as vscode from 'vscode';
+import * as os from 'os';
+import { normalizeJavaVersion } from './javaUtil';
+
+const GET_PROJECT_INFO = 'nbls.project.info';
+const GRADLE_TARGET_COMPATIBILITY_REGEX = 
/targetCompatibility\s*=\s*(?:JavaVersion\.toVersion\(['"](\d+(\.\d+)?)['"]\)|['"](\d+(\.\d+)?)['"])/

Review Comment:
   Nitpick: sadly the `JavaVersion.toVersion("string")` is a groovy script 
code, so there can be `\s*` between identifiers, literals and symbols. Unlikely 
to happen, though.



##########
java/java.lsp.server/vscode/src/jdk/validation/project.ts:
##########
@@ -0,0 +1,171 @@
+import * as xml2js from 'xml2js';
+import * as fs from 'fs';
+import * as path from 'path';
+import * as vscode from 'vscode';
+import * as os from 'os';
+import { normalizeJavaVersion } from './javaUtil';
+
+const GET_PROJECT_INFO = 'nbls.project.info';
+const GRADLE_TARGET_COMPATIBILITY_REGEX = 
/targetCompatibility\s*=\s*(?:JavaVersion\.toVersion\(['"](\d+(\.\d+)?)['"]\)|['"](\d+(\.\d+)?)['"])/
+const GRADLE_SOURCE_COMPATIBILITY_REGEX = 
/sourceCompatibility\s*=\s*(?:JavaVersion\.toVersion\(['"](\d+(\.\d+)?)['"]\)|['"](\d+(\.\d+)?)['"])/
+
+export enum BuildSystemType {
+    MAVEN = 'Maven',
+    GRADLE = 'Gradle',
+    UNKNOWN = 'Unknown'
+}
+
+export async function getProjectFrom(projectUri: vscode.Uri): Promise<Project 
| undefined> {
+    const projectInfos: any[] = await 
vscode.commands.executeCommand(GET_PROJECT_INFO, projectUri.toString(), { 
projectStructure: true });
+    if (projectInfos?.length && projectInfos[0]) {
+        const projectDirectory = projectInfos[0].projectDirectory.toString();
+        const buildSystem: BuildSystemType = 
resolveBuildSystemType(projectUri, projectInfos[0].projectType);
+
+        switch (buildSystem) {
+            case BuildSystemType.MAVEN:
+                const mavenSubprojects: Project[] = projectInfos[0].subprojects
+                    .map((subproject: string) => new MavenProject(subproject, 
[]))
+                return new MavenProject(projectDirectory, mavenSubprojects);
+            case BuildSystemType.GRADLE:
+                const gradleSubprojects: Project[] = 
projectInfos[0].subprojects
+                    .map((subproject: string) => new GradleProject(subproject, 
[]))
+                return new GradleProject(projectDirectory, gradleSubprojects);
+            default:
+                break;
+        }
+    }
+    return Promise.resolve(undefined);
+}
+
+function resolveBuildSystemType(uri: vscode.Uri, projectType?: string): 
BuildSystemType {
+    if (projectType?.includes('gradle')) {
+        return BuildSystemType.GRADLE;
+    }
+    if (projectType?.includes('maven')) {
+        return BuildSystemType.MAVEN;
+    }
+    if (fs.existsSync(path.join(uri.fsPath, 'build.gradle'))) {
+        return BuildSystemType.GRADLE;
+    }
+    if (fs.existsSync(path.join(uri.fsPath, 'pom.xml'))) {
+        return BuildSystemType.MAVEN;
+    }
+    return BuildSystemType.UNKNOWN;
+}
+
+export abstract class Project {
+
+    readonly directory: string;
+    readonly subprojects: Project[];
+
+    constructor(directory: string, subprojects: any[]) {
+        this.directory = directory.replace('file:/', '');
+        this.subprojects = subprojects;
+    }
+
+    // Whether the project contains subprojects
+    containsSubprojects(): boolean {
+        return this.subprojects.length > 0;
+    }
+
+    async getJavaVersion(): Promise<number | undefined> {
+        if (!this.containsSubprojects()) {
+            return this.extractJavaVersion();
+        }
+
+        let maxJavaVersion: number | undefined;
+
+        for (const subproject of this.subprojects) {
+            const subInfos: any[] = await 
vscode.commands.executeCommand(GET_PROJECT_INFO, 
`file:/${subproject.directory}`);
+            if (subInfos?.length && subInfos[0]) {
+                const javaVersion = subproject.extractJavaVersion();
+
+                if (!maxJavaVersion || (javaVersion && javaVersion > 
maxJavaVersion)) {
+                    maxJavaVersion = javaVersion;
+                }
+            }
+        }
+        return maxJavaVersion;
+    }
+
+    // Extracts project java version
+    protected abstract extractJavaVersion(): number | undefined
+}
+
+export class MavenProject extends Project {
+
+    constructor(directory: string, subprojects: any[]) {
+        super(directory, subprojects);
+    }
+
+    extractJavaVersion(): number | undefined {
+        const buildscript = path.resolve(this.directory, 'pom.xml');
+        let version: string | undefined;
+        if (fs.existsSync(buildscript)) {
+            xml2js.parseString(fs.readFileSync(buildscript)?.toString() || '', 
(err, result) => {
+                if (!err && result) {
+                    const properties = result['project']?.['properties'];
+                    if (properties && properties[0]) {

Review Comment:
   Nitpick: can use `properties?.[0]`



##########
java/java.lsp.server/vscode/src/jdk/validation/extensionUtils.ts:
##########
@@ -0,0 +1,28 @@
+import * as vscode from 'vscode';
+
+const RH_EXTENSION_ID = 'redhat.java';
+const EXTENSION_NBLS_ID = 'asf.apache-netbeans-java';
+const TIMEOUT_COMMAND_GET_PROJECT_INFO = 60; // wait for NBLS & projectInfo up 
to 60 seconds
+
+export function isRHExtensionActive(): boolean {
+    const rh = vscode.extensions.getExtension(RH_EXTENSION_ID);
+    return rh ? true : false;
+}
+
+export async function waitForNblsCommandToBeAvailable(command: string) {

Review Comment:
   There's `client` global variable in `extension.ts` which is a Promise to 
NBLS client initializaiton. Maybe you could use that for `await` or `.then`; if 
necessary, move that global to `utils.ts`.



##########
java/java.lsp.server/vscode/src/jdk/validation/project.ts:
##########
@@ -0,0 +1,171 @@
+import * as xml2js from 'xml2js';
+import * as fs from 'fs';
+import * as path from 'path';
+import * as vscode from 'vscode';
+import * as os from 'os';
+import { normalizeJavaVersion } from './javaUtil';
+
+const GET_PROJECT_INFO = 'nbls.project.info';
+const GRADLE_TARGET_COMPATIBILITY_REGEX = 
/targetCompatibility\s*=\s*(?:JavaVersion\.toVersion\(['"](\d+(\.\d+)?)['"]\)|['"](\d+(\.\d+)?)['"])/
+const GRADLE_SOURCE_COMPATIBILITY_REGEX = 
/sourceCompatibility\s*=\s*(?:JavaVersion\.toVersion\(['"](\d+(\.\d+)?)['"]\)|['"](\d+(\.\d+)?)['"])/
+
+export enum BuildSystemType {
+    MAVEN = 'Maven',
+    GRADLE = 'Gradle',
+    UNKNOWN = 'Unknown'
+}
+
+export async function getProjectFrom(projectUri: vscode.Uri): Promise<Project 
| undefined> {
+    const projectInfos: any[] = await 
vscode.commands.executeCommand(GET_PROJECT_INFO, projectUri.toString(), { 
projectStructure: true });

Review Comment:
   If searching for maximum required java, add `recursive: true` to also cover 
grand-child subprojects.



##########
java/java.lsp.server/vscode/src/jdk/validation/project.ts:
##########
@@ -0,0 +1,171 @@
+import * as xml2js from 'xml2js';
+import * as fs from 'fs';
+import * as path from 'path';
+import * as vscode from 'vscode';
+import * as os from 'os';
+import { normalizeJavaVersion } from './javaUtil';
+
+const GET_PROJECT_INFO = 'nbls.project.info';
+const GRADLE_TARGET_COMPATIBILITY_REGEX = 
/targetCompatibility\s*=\s*(?:JavaVersion\.toVersion\(['"](\d+(\.\d+)?)['"]\)|['"](\d+(\.\d+)?)['"])/
+const GRADLE_SOURCE_COMPATIBILITY_REGEX = 
/sourceCompatibility\s*=\s*(?:JavaVersion\.toVersion\(['"](\d+(\.\d+)?)['"]\)|['"](\d+(\.\d+)?)['"])/
+
+export enum BuildSystemType {
+    MAVEN = 'Maven',
+    GRADLE = 'Gradle',
+    UNKNOWN = 'Unknown'
+}
+
+export async function getProjectFrom(projectUri: vscode.Uri): Promise<Project 
| undefined> {
+    const projectInfos: any[] = await 
vscode.commands.executeCommand(GET_PROJECT_INFO, projectUri.toString(), { 
projectStructure: true });
+    if (projectInfos?.length && projectInfos[0]) {
+        const projectDirectory = projectInfos[0].projectDirectory.toString();
+        const buildSystem: BuildSystemType = 
resolveBuildSystemType(projectUri, projectInfos[0].projectType);
+
+        switch (buildSystem) {
+            case BuildSystemType.MAVEN:
+                const mavenSubprojects: Project[] = projectInfos[0].subprojects
+                    .map((subproject: string) => new MavenProject(subproject, 
[]))
+                return new MavenProject(projectDirectory, mavenSubprojects);
+            case BuildSystemType.GRADLE:
+                const gradleSubprojects: Project[] = 
projectInfos[0].subprojects
+                    .map((subproject: string) => new GradleProject(subproject, 
[]))
+                return new GradleProject(projectDirectory, gradleSubprojects);
+            default:
+                break;
+        }
+    }
+    return Promise.resolve(undefined);
+}
+
+function resolveBuildSystemType(uri: vscode.Uri, projectType?: string): 
BuildSystemType {
+    if (projectType?.includes('gradle')) {
+        return BuildSystemType.GRADLE;
+    }
+    if (projectType?.includes('maven')) {
+        return BuildSystemType.MAVEN;
+    }
+    if (fs.existsSync(path.join(uri.fsPath, 'build.gradle'))) {
+        return BuildSystemType.GRADLE;
+    }
+    if (fs.existsSync(path.join(uri.fsPath, 'pom.xml'))) {
+        return BuildSystemType.MAVEN;
+    }
+    return BuildSystemType.UNKNOWN;
+}
+
+export abstract class Project {
+
+    readonly directory: string;
+    readonly subprojects: Project[];
+
+    constructor(directory: string, subprojects: any[]) {
+        this.directory = directory.replace('file:/', '');

Review Comment:
   Note: this may produce `C:/Temp/whatever` paths on Windows. Possibly 
transform e.g. using `vscode.Uri.parse(directory).fsPath`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to