All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonarsource.sonarlint.ls.EnginesFactory Maven / Gradle / Ivy

There is a newer version: 3.12.0.75621
Show newest version
/*
 * SonarLint Language Server
 * Copyright (C) 2009-2023 SonarSource SA
 * mailto:info AT sonarsource DOT com
 *
 * 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  02110-1301, USA.
 */
package org.sonarsource.sonarlint.ls;

import java.nio.file.Path;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import org.jetbrains.annotations.NotNull;
import org.sonarsource.sonarlint.core.ConnectedSonarLintEngineImpl;
import org.sonarsource.sonarlint.core.StandaloneSonarLintEngineImpl;
import org.sonarsource.sonarlint.core.analysis.api.ClientModulesProvider;
import org.sonarsource.sonarlint.core.client.api.connected.ConnectedGlobalConfiguration;
import org.sonarsource.sonarlint.core.client.api.connected.ConnectedSonarLintEngine;
import org.sonarsource.sonarlint.core.client.api.standalone.StandaloneGlobalConfiguration;
import org.sonarsource.sonarlint.core.client.api.standalone.StandaloneSonarLintEngine;
import org.sonarsource.sonarlint.core.commons.Language;
import org.sonarsource.sonarlint.core.commons.log.ClientLogOutput;
import org.sonarsource.sonarlint.ls.log.LanguageClientLogOutput;
import org.sonarsource.sonarlint.ls.settings.ServerConnectionSettings;

import static java.lang.String.format;

public class EnginesFactory {

  public static Path sonarLintUserHomeOverride = null;
  private final LanguageClientLogOutput logOutput;
  private final Collection standaloneAnalyzers;
  private final Map embeddedPluginsToPath;
  private String omnisharpDirectory;


  private static final Language[] STANDALONE_LANGUAGES = {
    Language.AZURERESOURCEMANAGER,
    Language.CPP,
    Language.C,
    Language.CLOUDFORMATION,
    Language.CS,
    Language.CSS,
    Language.DOCKER,
    Language.GO,
    Language.HTML,
    Language.IPYTHON,
    Language.JAVA,
    Language.JS,
    Language.JSON,
    Language.KUBERNETES,
    Language.PHP,
    Language.PYTHON,
    Language.SECRETS,
    Language.TERRAFORM,
    Language.TS,
    Language.XML,
    Language.YAML,
  };

  private static final Language[] CONNECTED_ADDITIONAL_LANGUAGES = {
    Language.APEX,
    Language.COBOL,
    Language.PLSQL,
    Language.TSQL
  };

  private final NodeJsRuntime nodeJsRuntime;
  private final ClientModulesProvider modulesProvider;
  private final AtomicReference shutdown = new AtomicReference<>(false);

  public EnginesFactory(Collection standaloneAnalyzers, Map embeddedPluginsToPath,
    LanguageClientLogOutput globalLogOutput, NodeJsRuntime nodeJsRuntime, ClientModulesProvider modulesProvider) {
    this.standaloneAnalyzers = standaloneAnalyzers;
    this.embeddedPluginsToPath = embeddedPluginsToPath;
    this.logOutput = globalLogOutput;
    this.nodeJsRuntime = nodeJsRuntime;
    this.modulesProvider = modulesProvider;
  }

  public void setOmnisharpDirectory(String omnisharpDirectory) {
    this.omnisharpDirectory = omnisharpDirectory;
  }

  public StandaloneSonarLintEngine createStandaloneEngine() {
    if (shutdown.get().equals(true)) {
      throw new IllegalStateException("Language server is shutting down, won't create engine");
    }
    logOutput.log("Starting standalone SonarLint engine...", ClientLogOutput.Level.DEBUG);
    logOutput.log(format("Using %d analyzers", standaloneAnalyzers.size()), ClientLogOutput.Level.DEBUG);

    try {
      var configuration = StandaloneGlobalConfiguration.builder()
        .setSonarLintUserHome(sonarLintUserHomeOverride)
        .addEnabledLanguages(STANDALONE_LANGUAGES)
        .setNodeJs(nodeJsRuntime.getNodeJsPath(), nodeJsRuntime.getNodeJsVersion())
        .addPlugins(standaloneAnalyzers.toArray(Path[]::new))
        .setModulesProvider(modulesProvider)
        .setExtraProperties(getExtraProperties())
        .setLogOutput(logOutput)
        .build();

      var engine = newStandaloneEngine(configuration);
      logOutput.log("Standalone SonarLint engine started", ClientLogOutput.Level.DEBUG);
      return engine;
    } catch (Exception e) {
      logOutput.log(format("Error starting standalone SonarLint engine %s", e), ClientLogOutput.Level.ERROR);
      throw new IllegalStateException(e);
    }
  }

  StandaloneSonarLintEngine newStandaloneEngine(StandaloneGlobalConfiguration configuration) {
    return new StandaloneSonarLintEngineImpl(configuration);
  }

  public ConnectedSonarLintEngine createConnectedEngine(String connectionId,
    ServerConnectionSettings serverConnectionSettings) {
    if (shutdown.get().equals(true)) {
      throw new IllegalStateException("Language server is shutting down, won't create engine");
    }
    ConnectedGlobalConfiguration.Builder builder;
    if (serverConnectionSettings.isSonarCloudAlias()) {
      builder = ConnectedGlobalConfiguration.sonarCloudBuilder();
    } else {
      builder = ConnectedGlobalConfiguration.sonarQubeBuilder();
    }
    builder
      .setSonarLintUserHome(sonarLintUserHomeOverride)
      .setConnectionId(connectionId)
      .addEnabledLanguages(STANDALONE_LANGUAGES)
      .addEnabledLanguages(CONNECTED_ADDITIONAL_LANGUAGES)
      .enableDataflowBugDetection()
      .enableHotspots()
      .setNodeJs(nodeJsRuntime.getNodeJsPath(), nodeJsRuntime.getNodeJsVersion())
      .setModulesProvider(modulesProvider)
      .setExtraProperties(getExtraProperties())
      .setLogOutput(logOutput);

    embeddedPluginsToPath.forEach(builder::useEmbeddedPlugin);

    var engine = newConnectedEngine(builder.build());

    logOutput.log(format("SonarLint engine started for connection '%s'", connectionId), ClientLogOutput.Level.DEBUG);
    return engine;
  }

  @NotNull
  private Map getExtraProperties() {
    if (omnisharpDirectory == null) {
      return Map.of();
    } else {
      return Map.of(
        "sonar.cs.internal.omnisharpNet6Location", Path.of(omnisharpDirectory, "net6").toString(),
        "sonar.cs.internal.omnisharpWinLocation", Path.of(omnisharpDirectory, "net472").toString(),
        "sonar.cs.internal.omnisharpMonoLocation", Path.of(omnisharpDirectory, "mono").toString()
      );
    }
  }

  ConnectedSonarLintEngine newConnectedEngine(ConnectedGlobalConfiguration configuration) {
    return new ConnectedSonarLintEngineImpl(configuration);
  }

  public static Set getStandaloneLanguages() {
    return EnumSet.copyOf(List.of(STANDALONE_LANGUAGES));
  }

  public static Set getConnectedLanguages() {
    return Set.of(CONNECTED_ADDITIONAL_LANGUAGES);
  }

  public void shutdown() {
    shutdown.set(true);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy