diff --git a/pom.xml b/pom.xml index 237d7c8..0d9d37d 100644 --- a/pom.xml +++ b/pom.xml @@ -149,6 +149,11 @@ sonarlint-core 6.3.0.36253 + + org.sonarsource.javascript + nodejs-utils + 8.3.0.16208 + com.google.code.gson gson diff --git a/src/main/java/com/github/philippefichet/sonarlint4netbeans/NodeProcessWrapper.java b/src/main/java/com/github/philippefichet/sonarlint4netbeans/NodeProcessWrapper.java new file mode 100644 index 0000000..02433e9 --- /dev/null +++ b/src/main/java/com/github/philippefichet/sonarlint4netbeans/NodeProcessWrapper.java @@ -0,0 +1,85 @@ +/* + * sonarlint4netbeans: SonarLint integration for Apache Netbeans + * Copyright (C) 2020 Philippe FICHET. + * + * This library 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 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package com.github.philippefichet.sonarlint4netbeans; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import org.sonarsource.nodejs.ProcessWrapper; +import org.sonarsource.nodejs.ProcessWrapperImpl; + +/** + * Used to intercept nodejs path in NodeCommandBuilderImpl + * @author FICHET Philippe <philippe.fichet@laposte.net> + */ +public class NodeProcessWrapper implements ProcessWrapper { + + private final ProcessWrapperImpl processWrapper = new ProcessWrapperImpl(); + private List commandLineUsed = null; + + @Override + public Process startProcess(List commandLine, Map env, Consumer outputConsumer, Consumer errorConsumer) throws IOException { + commandLineUsed = new ArrayList<>(commandLine); + return processWrapper.startProcess(commandLine, env, outputConsumer, errorConsumer); + } + + @Override + public boolean waitFor(Process process, long timeout, TimeUnit unit) throws InterruptedException { + return processWrapper.waitFor(process, timeout, unit); + } + + @Override + public void interrupt() { + processWrapper.interrupt(); + } + + @Override + public void destroyForcibly(Process process) { + processWrapper.destroyForcibly(process); + } + + @Override + public boolean isMac() { + return processWrapper.isMac(); + } + + @Override + public boolean isWindows() { + return processWrapper.isWindows(); + } + + @Override + public String getenv(String name) { + return processWrapper.getenv(name); + } + + @Override + public int exitValue(Process process) { + return processWrapper.exitValue(process); + } + + public Optional> getCommandLineUsed() { + return Optional.ofNullable(commandLineUsed); + } +} diff --git a/src/main/java/com/github/philippefichet/sonarlint4netbeans/SonarLintEngineImpl.java b/src/main/java/com/github/philippefichet/sonarlint4netbeans/SonarLintEngineImpl.java index a83f44a..17f3ada 100644 --- a/src/main/java/com/github/philippefichet/sonarlint4netbeans/SonarLintEngineImpl.java +++ b/src/main/java/com/github/philippefichet/sonarlint4netbeans/SonarLintEngineImpl.java @@ -20,6 +20,7 @@ package com.github.philippefichet.sonarlint4netbeans; import com.google.gson.Gson; +import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Path; @@ -35,6 +36,9 @@ import java.util.logging.Logger; import java.util.prefs.Preferences; import org.openide.util.NbPreferences; +import org.sonarsource.nodejs.NodeCommand; +import org.sonarsource.nodejs.NodeCommandBuilderImpl; +import org.sonarsource.nodejs.NodeCommandException; import org.sonarsource.sonarlint.core.StandaloneSonarLintEngineImpl; import org.sonarsource.sonarlint.core.client.api.common.Language; import org.sonarsource.sonarlint.core.client.api.common.LogOutput; @@ -109,17 +113,40 @@ private void createInternalEngine() { StandaloneGlobalConfiguration.Builder configBuilder = StandaloneGlobalConfiguration.builder() .addEnabledLanguages(Language.values()) .addPlugins(pluginURLs.values().toArray(new URL[pluginURLs.values().size()])); - getNodeJSPath().ifPresent(nodeJSPath -> { - getNodeJSVersion().ifPresent(nodeJSVersion -> { - Path nodeJS = Paths.get(nodeJSPath); - configBuilder.setNodeJs(nodeJS, nodeJSVersion); - }); - }); + if (getNodeJSPath().isPresent() && getNodeJSVersion().isPresent()) { + String nodeJSPath = getNodeJSPath().get(); + Version nodeJSVersion = getNodeJSVersion().get(); + Path nodeJS = Paths.get(nodeJSPath); + configBuilder.setNodeJs(nodeJS, nodeJSVersion); + } else { + tryToSetDefaultNodeJS(configBuilder); + } standaloneSonarLintEngineImpl = new StandaloneSonarLintEngineImpl(configBuilder.build()); consumerWaitingInitialization.forEach(consumer -> consumer.accept(this)); consumerWaitingInitialization.clear(); }).start(); } + + private void tryToSetDefaultNodeJS(StandaloneGlobalConfiguration.Builder configBuilder) { + try { + NodeProcessWrapper nodeProcessWrapper = new NodeProcessWrapper(); + NodeCommand nodeCommandVersion = new NodeCommandBuilderImpl(nodeProcessWrapper) + .nodeJsArgs("--version") + .build(); + nodeCommandVersion.start(); + if (nodeCommandVersion.waitFor() == 0 && nodeProcessWrapper.getCommandLineUsed().isPresent()) { + String nodeJSPath = nodeProcessWrapper.getCommandLineUsed().get().get(0); + Optional detectNodeJSVersion = SonarLintUtils.detectNodeJSVersion(nodeJSPath); + if (detectNodeJSVersion.isPresent()) { + configBuilder.setNodeJs(Paths.get(nodeJSPath), detectNodeJSVersion.get()); + Logger.getLogger(SonarLintEngineImpl.class.getName()).log(Level.SEVERE, "Use default nodejs path"); + } + } + } catch (NodeCommandException | IOException ex) { + Logger.getLogger(SonarLintEngineImpl.class.getName()).log(Level.SEVERE, null, ex); + } + } + @Override public Optional getNodeJSPath() {