Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SLI-1827 [WIP] Rely on NodeJs from IDE configuration #1295

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ dependencies {
compileOnly(libs.findbugs.jsr305)
runtimeOnly(project(":clion"))
runtimeOnly(project(":clion-resharper"))
runtimeOnly(project(":nodejs"))
runtimeOnly(project(":rider"))
runtimeOnly(project(":git"))
testImplementation(platform(libs.junit.bom))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* SonarLint for IntelliJ IDEA
* Copyright (C) 2015-2025 SonarSource
* [email protected]
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonarlint.intellij.common.util;

import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import java.nio.file.Path;
import javax.annotation.Nullable;

public interface NodeJsProvider {

// Name is constructed from plugin-id.extension-point-name
ExtensionPointName<NodeJsProvider> EP_NAME = ExtensionPointName.create("org.sonarlint.idea.nodeJsProvider");

@Nullable
Path getNodeJsPathFor(Project project);

}
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ riderBuildVersion=RD-2022.3.1
clionBuildVersion=CL-2022.3.1
clionResharperBuildVersion=RD-2024.1
intellijBuildVersion=IC-2022.3.1
intellijUltimateBuildVersion=IU-2022.3.1
20 changes: 20 additions & 0 deletions nodejs/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
val intellijUltimateBuildVersion: String by project
val ideaHome: String? = System.getenv("IDEA_HOME")

plugins {
kotlin("jvm")
}

intellij {
if (!ideaHome.isNullOrBlank()) {
localPath.set(ideaHome)
localSourcesPath.set(ideaHome)
} else {
version.set(intellijUltimateBuildVersion)
}
plugins.set(listOf("JavaScript"))
}

dependencies {
implementation(project(":common"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* SonarLint for IntelliJ IDEA
* Copyright (C) 2015-2025 SonarSource
* [email protected]
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonarlint.intellij.nodejs;

import com.intellij.javascript.nodejs.interpreter.NodeJsInterpreterManager;
import com.intellij.openapi.project.Project;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.jetbrains.annotations.Nullable;
import org.sonarlint.intellij.common.util.NodeJsProvider;

public class JavaScriptNodeJsProvider implements NodeJsProvider {

@Nullable
@Override
public Path getNodeJsPathFor(Project project) {
var interpreter = NodeJsInterpreterManager.getInstance(project).getInterpreter();
return interpreter != null ? Paths.get(interpreter.getReferenceName()) : null;
}

}
2 changes: 1 addition & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
rootProject.name = "sonarlint-intellij"
include("its", "clion", "clion-resharper", "clion-common", "common", "git", "rider")
include("its", "clion", "clion-resharper", "nodejs", "clion-common", "common", "git", "rider")

dependencyResolutionManagement {
versionCatalogs {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import java.nio.file.Paths
import java.security.cert.CertificateException
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import java.time.Duration
import java.util.UUID
import java.util.concurrent.CancellationException
import java.util.concurrent.CompletableFuture
Expand Down Expand Up @@ -111,6 +112,7 @@ import org.sonarlint.intellij.sharing.ConfigurationSharing
import org.sonarlint.intellij.sharing.SonarLintSharedFolderUtils.Companion.findSharedFolder
import org.sonarlint.intellij.trigger.TriggerType
import org.sonarlint.intellij.ui.UiUtils.Companion.runOnUiThread
import org.sonarlint.intellij.util.FutureUtils
import org.sonarlint.intellij.util.GlobalLogOutput
import org.sonarlint.intellij.util.ProjectUtils.tryFindFile
import org.sonarlint.intellij.util.SonarLintAppUtils.findModuleForFile
Expand All @@ -133,7 +135,6 @@ import org.sonarsource.sonarlint.core.rpc.protocol.client.binding.NoBindingSugge
import org.sonarsource.sonarlint.core.rpc.protocol.client.connection.AssistCreatingConnectionParams
import org.sonarsource.sonarlint.core.rpc.protocol.client.connection.AssistCreatingConnectionResponse
import org.sonarsource.sonarlint.core.rpc.protocol.client.connection.ConnectionSuggestionDto
import org.sonarsource.sonarlint.core.rpc.protocol.client.event.DidReceiveServerHotspotEvent
import org.sonarsource.sonarlint.core.rpc.protocol.client.fix.FixSuggestionDto
import org.sonarsource.sonarlint.core.rpc.protocol.client.hotspot.HotspotDetailsDto
import org.sonarsource.sonarlint.core.rpc.protocol.client.hotspot.RaisedHotspotDto
Expand Down Expand Up @@ -632,7 +633,9 @@ object SonarLintIntelliJClient : SonarLintRpcClientDelegate {
resultFuture.complete(result)
}
})
return computeOnPooledThread(project, "Waiting for branch matching result") { resultFuture.get() }
return computeOnPooledThread(project, "Waiting for branch matching result") {
FutureUtils.waitForTask(resultFuture, "", Duration.ofSeconds(10))
}
}

override fun matchProjectBranch(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.ui.HyperlinkAdapter;
import com.intellij.ui.components.JBCheckBox;
Expand All @@ -34,6 +35,7 @@
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Objects;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
Expand All @@ -42,6 +44,7 @@
import javax.swing.JPanel;
import javax.swing.event.HyperlinkEvent;
import org.sonarlint.intellij.cayc.CleanAsYouCodeService;
import org.sonarlint.intellij.common.util.NodeJsProvider;
import org.sonarlint.intellij.config.ConfigurationPanel;
import org.sonarlint.intellij.core.BackendService;
import org.sonarlint.intellij.util.HelpLabelUtils;
Expand Down Expand Up @@ -144,15 +147,30 @@ public void load(SonarLintGlobalSettings model) {

private void loadNodeJsSettings(SonarLintGlobalSettings model) {
if (model.getNodejsPath() == null || model.getNodejsPath().isBlank()) {
getService(BackendService.class).getAutoDetectedNodeJs().thenAccept(settings -> {
if (settings == null) {
this.nodeJsPath.getEmptyText().setText("Node.js not found");
this.nodeJsVersion.setText("N/A");
} else {
this.nodeJsPath.getEmptyText().setText(settings.getPath().toString());
this.nodeJsVersion.setText(settings.getVersion());
}
});
var optProject = Arrays.stream(ProjectManager.getInstance().getOpenProjects()).findFirst();
if (optProject.isPresent()) {
var optNodeJs = NodeJsProvider.EP_NAME.getExtensionList().stream().map(e ->
e.getNodeJsPathFor(optProject.get())
).findFirst();
optNodeJs.ifPresent(path -> getService(BackendService.class).changeClientNodeJsPath(path).thenAccept(settings -> {
if (settings == null) {
this.nodeJsVersion.setText("N/A");
} else {
this.nodeJsPath.setText(settings.getPath().toString());
this.nodeJsVersion.setText(settings.getVersion());
}
}));
} else {
getService(BackendService.class).getAutoDetectedNodeJs().thenAccept(settings -> {
if (settings == null) {
this.nodeJsPath.getEmptyText().setText("Node.js not found");
this.nodeJsVersion.setText("N/A");
} else {
this.nodeJsPath.getEmptyText().setText(settings.getPath().toString());
this.nodeJsVersion.setText(settings.getVersion());
}
});
}
} else {
var forcedNodeJsPath = Paths.get(model.getNodejsPath());
getService(BackendService.class).changeClientNodeJsPath(forcedNodeJsPath).thenAccept(settings -> {
Expand Down
26 changes: 26 additions & 0 deletions src/main/resources/META-INF/plugin-nodejs.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!--

SonarLint for IntelliJ IDEA
Copyright (C) 2015-2025 SonarSource
[email protected]

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02

-->
<idea-plugin>
<extensions defaultExtensionNs="org.sonarlint.idea">
<nodeJsProvider implementation="org.sonarlint.intellij.nodejs.JavaScriptNodeJsProvider"/>
</extensions>
</idea-plugin>
2 changes: 2 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@
<depends optional="true" config-file="plugin-clion-resharper.xml">org.jetbrains.plugins.clion.radler</depends>
<depends optional="true" config-file="plugin-rider.xml">com.intellij.modules.rider</depends>
<depends optional="true" config-file="plugin-jupyter.xml">intellij.jupyter</depends>
<depends optional="true" config-file="plugin-nodejs.xml">JavaScript</depends>

<projectListeners>
<listener class="org.sonarlint.intellij.module.ModuleChangeListener" topic="com.intellij.openapi.project.ModuleListener"/>
Expand Down Expand Up @@ -287,6 +288,7 @@
<extensionPoint name="fileExclusionContributor" interface="org.sonarlint.intellij.common.analysis.FileExclusionContributor" dynamic="true"/>
<extensionPoint name="filesContributor" interface="org.sonarlint.intellij.common.analysis.FilesContributor" dynamic="true"/>
<extensionPoint name="vcsProvider" interface="org.sonarlint.intellij.common.vcs.VcsRepoProvider" dynamic="true"/>
<extensionPoint name="nodeJsProvider" interface="org.sonarlint.intellij.common.util.NodeJsProvider" dynamic="true"/>
</extensionPoints>

<applicationListeners>
Expand Down