Skip to content

Commit 94327f2

Browse files
committed
SLCORE-2242 Add embedded, unsupported and premium artifact resolvers
1 parent f5fc710 commit 94327f2

File tree

8 files changed

+781
-0
lines changed

8 files changed

+781
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* SonarLint Core - Implementation
3+
* Copyright (C) 2016-2025 SonarSource Sàrl
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonarsource.sonarlint.core.plugin.resolvers;
21+
22+
import java.nio.file.Path;
23+
import java.util.Map;
24+
import java.util.Optional;
25+
import java.util.Set;
26+
import java.util.function.Function;
27+
import java.util.stream.Collectors;
28+
import javax.annotation.Nullable;
29+
import org.sonarsource.sonarlint.core.commons.api.SonarLanguage;
30+
import org.sonarsource.sonarlint.core.plugin.ArtifactSource;
31+
import org.sonarsource.sonarlint.core.plugin.ArtifactState;
32+
import org.sonarsource.sonarlint.core.plugin.PluginJarUtils;
33+
import org.sonarsource.sonarlint.core.plugin.PluginStatus;
34+
import org.sonarsource.sonarlint.core.plugin.ResolvedArtifact;
35+
import org.sonarsource.sonarlint.core.plugin.commons.loading.SonarPluginManifest;
36+
import org.sonarsource.sonarlint.core.rpc.protocol.backend.initialize.InitializeParams;
37+
import org.sonarsource.sonarlint.core.rpc.protocol.backend.initialize.LanguageSpecificRequirements;
38+
import org.sonarsource.sonarlint.core.rpc.protocol.backend.initialize.OmnisharpRequirementsDto;
39+
40+
public class EmbeddedArtifactResolver implements ArtifactResolver, CompanionPluginResolver {
41+
42+
private final Map<String, Path> standaloneEmbeddedPathsByKey;
43+
private final Map<String, Path> connectedModeEmbeddedPathsByKey;
44+
@Nullable
45+
private final Path csharpStandalonePluginPath;
46+
47+
public EmbeddedArtifactResolver(InitializeParams params) {
48+
this.standaloneEmbeddedPathsByKey = buildPluginKeyToPathMap(params.getEmbeddedPluginPaths());
49+
this.connectedModeEmbeddedPathsByKey = params.getConnectedModeEmbeddedPluginPathsByKey();
50+
this.csharpStandalonePluginPath = Optional.ofNullable(params.getLanguageSpecificRequirements())
51+
.map(LanguageSpecificRequirements::getOmnisharpRequirements)
52+
.map(OmnisharpRequirementsDto::getOssAnalyzerPath)
53+
.orElse(null);
54+
}
55+
56+
@Override
57+
public Optional<ResolvedArtifact> resolve(SonarLanguage language, @Nullable String connectionId) {
58+
return Optional.ofNullable(resolvePath(language, connectionId))
59+
.map(EmbeddedArtifactResolver::toResolvedArtifact);
60+
}
61+
62+
@Override
63+
public Map<String, PluginStatus> resolveCompanionPlugins(@Nullable String connectionId) {
64+
return standaloneEmbeddedPathsByKey.entrySet().stream()
65+
.filter(e -> !SonarLanguage.ALL_PLUGIN_KEYS.contains(e.getKey()))
66+
.collect(Collectors.toMap(
67+
Map.Entry::getKey,
68+
e -> PluginStatus.forCompanion(e.getKey(), ArtifactState.ACTIVE, ArtifactSource.EMBEDDED, e.getValue())));
69+
}
70+
71+
@Nullable
72+
private Path resolvePath(SonarLanguage language, @Nullable String connectionId) {
73+
return connectionId != null ? resolveConnected(language) : resolveStandalone(language);
74+
}
75+
76+
private static ResolvedArtifact toResolvedArtifact(Path path) {
77+
return new ResolvedArtifact(ArtifactState.ACTIVE, path, ArtifactSource.EMBEDDED, PluginJarUtils.readVersion(path));
78+
}
79+
80+
@Nullable
81+
private Path resolveConnected(SonarLanguage language) {
82+
return connectedModeEmbeddedPathsByKey.get(language.getPluginKey());
83+
}
84+
85+
@Nullable
86+
private Path resolveStandalone(SonarLanguage language) {
87+
var found = standaloneEmbeddedPathsByKey.get(language.getPluginKey());
88+
if (found == null && language == SonarLanguage.CS) {
89+
return csharpStandalonePluginPath;
90+
}
91+
return found;
92+
}
93+
94+
private static Map<String, Path> buildPluginKeyToPathMap(Set<Path> embeddedPaths) {
95+
return embeddedPaths.stream()
96+
.collect(Collectors.toMap(p -> SonarPluginManifest.fromJar(p).getKey(), Function.identity()));
97+
}
98+
99+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* SonarLint Core - Implementation
3+
* Copyright (C) 2016-2025 SonarSource Sàrl
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonarsource.sonarlint.core.plugin.resolvers;
21+
22+
import java.nio.file.Path;
23+
import java.util.LinkedHashMap;
24+
import java.util.Map;
25+
import java.util.Optional;
26+
import javax.annotation.Nullable;
27+
import org.sonarsource.sonarlint.core.plugin.ondemand.DownloadableArtifact;
28+
import org.sonarsource.sonarlint.core.rpc.protocol.backend.initialize.InitializeParams;
29+
import org.sonarsource.sonarlint.core.rpc.protocol.backend.initialize.LanguageSpecificRequirements;
30+
31+
public class EmbeddedExtraArtifactResolver implements ExtraArtifactResolver {
32+
33+
private final Map<String, Path> paths;
34+
35+
public EmbeddedExtraArtifactResolver(InitializeParams params) {
36+
this.paths = buildPaths(params.getLanguageSpecificRequirements());
37+
}
38+
39+
@Override
40+
public Optional<Path> resolve(String artifactKey) {
41+
return Optional.ofNullable(paths.get(artifactKey));
42+
}
43+
44+
private static Map<String, Path> buildPaths(@Nullable LanguageSpecificRequirements requirements) {
45+
if (requirements == null) {
46+
return Map.of();
47+
}
48+
var dto = requirements.getOmnisharpRequirements();
49+
if (dto == null) {
50+
return Map.of();
51+
}
52+
var result = new LinkedHashMap<String, Path>();
53+
addIfNotNull(result, DownloadableArtifact.OMNISHARP_MONO.artifactKey(), dto.getMonoDistributionPath());
54+
addIfNotNull(result, DownloadableArtifact.OMNISHARP_NET6.artifactKey(), dto.getDotNet6DistributionPath());
55+
addIfNotNull(result, DownloadableArtifact.OMNISHARP_WIN.artifactKey(), dto.getDotNet472DistributionPath());
56+
return Map.copyOf(result);
57+
}
58+
59+
private static void addIfNotNull(Map<String, Path> map, String key, @Nullable Path value) {
60+
if (value != null) {
61+
map.put(key, value);
62+
}
63+
}
64+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* SonarLint Core - Implementation
3+
* Copyright (C) 2016-2025 SonarSource Sàrl
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonarsource.sonarlint.core.plugin.resolvers;
21+
22+
import java.util.Optional;
23+
import javax.annotation.Nullable;
24+
import org.sonarsource.sonarlint.core.commons.api.SonarLanguage;
25+
import org.sonarsource.sonarlint.core.languages.LanguageSupportRepository;
26+
import org.sonarsource.sonarlint.core.plugin.ArtifactState;
27+
import org.sonarsource.sonarlint.core.plugin.ResolvedArtifact;
28+
29+
public class PremiumArtifactResolver implements ArtifactResolver {
30+
31+
private final LanguageSupportRepository languageSupportRepository;
32+
33+
public PremiumArtifactResolver(LanguageSupportRepository languageSupportRepository) {
34+
this.languageSupportRepository = languageSupportRepository;
35+
}
36+
37+
@Override
38+
public Optional<ResolvedArtifact> resolve(SonarLanguage language, @Nullable String connectionId) {
39+
if (languageSupportRepository.isEnabledInConnectedMode(language)
40+
&& !languageSupportRepository.isEnabledInStandaloneMode(language)) {
41+
return Optional.of(new ResolvedArtifact(ArtifactState.PREMIUM, null, null, null));
42+
}
43+
return Optional.empty();
44+
}
45+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* SonarLint Core - Implementation
3+
* Copyright (C) 2016-2025 SonarSource Sàrl
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonarsource.sonarlint.core.plugin.resolvers;
21+
22+
import java.util.Optional;
23+
import javax.annotation.Nullable;
24+
import org.sonarsource.sonarlint.core.commons.api.SonarLanguage;
25+
import org.sonarsource.sonarlint.core.commons.log.SonarLintLogger;
26+
import org.sonarsource.sonarlint.core.languages.LanguageSupportRepository;
27+
import org.sonarsource.sonarlint.core.plugin.ArtifactState;
28+
import org.sonarsource.sonarlint.core.plugin.ResolvedArtifact;
29+
30+
public class UnsupportedArtifactResolver implements ArtifactResolver {
31+
32+
private static final SonarLintLogger LOG = SonarLintLogger.get();
33+
34+
private final LanguageSupportRepository languageSupportRepository;
35+
36+
public UnsupportedArtifactResolver(LanguageSupportRepository languageSupportRepository) {
37+
this.languageSupportRepository = languageSupportRepository;
38+
}
39+
40+
@Override
41+
public Optional<ResolvedArtifact> resolve(SonarLanguage language, @Nullable String connectionId) {
42+
if (!isSupported(language, connectionId)) {
43+
if (connectionId != null) {
44+
LOG.debug("[SYNC] Code analyzer '{}' is disabled in SonarLint (language not enabled). Skip downloading it.",
45+
language.getPluginKey());
46+
}
47+
return Optional.of(new ResolvedArtifact(ArtifactState.UNSUPPORTED, null, null, null));
48+
}
49+
return Optional.empty();
50+
}
51+
52+
private boolean isSupported(SonarLanguage language, @Nullable String connectionId) {
53+
return (languageSupportRepository.isEnabledInStandaloneMode(language) && connectionId == null)
54+
|| languageSupportRepository.isEnabledInConnectedMode(language);
55+
}
56+
}

0 commit comments

Comments
 (0)