Skip to content

Commit 00df27b

Browse files
SLLS-266 correctly handle JSON values in settings
1 parent b973712 commit 00df27b

File tree

2 files changed

+97
-14
lines changed

2 files changed

+97
-14
lines changed

src/main/java/org/sonarsource/sonarlint/ls/settings/SettingsManager.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@
2020
package org.sonarsource.sonarlint.ls.settings;
2121

2222
import com.google.common.collect.Maps;
23+
import com.google.gson.Gson;
24+
import com.google.gson.JsonElement;
2325
import com.google.gson.JsonObject;
26+
import com.google.gson.JsonParseException;
2427
import java.net.URI;
28+
import java.nio.file.InvalidPathException;
2529
import java.nio.file.Path;
2630
import java.nio.file.Paths;
2731
import java.util.ArrayList;
@@ -281,24 +285,39 @@ static Map<String, Object> updateProperties(@org.jetbrains.annotations.Nullable
281285
var analyzerProperties = (Map<String, String>) (sonarLintSettingsMap == null ?
282286
Maps.newHashMap() :
283287
sonarLintSettingsMap.getOrDefault(ANALYZER_PROPERTIES, Maps.newHashMap()));
284-
var analysisExcludes = (String) settingsMap.getOrDefault(ANALYSIS_EXCLUDES, "");
288+
var analysisExcludes = getStringValue(settingsMap, ANALYSIS_EXCLUDES, "");
285289
forceIgnoreRazorFiles(analyzerProperties);
286-
var solutionRelativePath = settingsMap.getOrDefault(DOTNET_DEFAULT_SOLUTION_PATH, "").toString();
290+
var solutionRelativePath = getStringValue(settingsMap, DOTNET_DEFAULT_SOLUTION_PATH, "");
287291
if (!solutionRelativePath.isEmpty() && workspaceUri != null) {
288292
// uri: file:///Users/me/Documents/Sonar/roslyn
289293
// solutionPath: Roslyn.sln
290294
// we want: /Users/me/Documents/Sonar/roslyn/Roslyn.sln
291-
analyzerProperties.put("sonar.cs.internal.solutionPath", Path.of(workspaceUri).resolve(solutionRelativePath).toAbsolutePath().toString());
295+
try {
296+
analyzerProperties.put("sonar.cs.internal.solutionPath", Path.of(workspaceUri).resolve(solutionRelativePath).toAbsolutePath().toString());
297+
} catch (InvalidPathException e) {
298+
analyzerProperties.put("sonar.cs.internal.solutionPath", "");
299+
}
292300
}
293-
analyzerProperties.put("sonar.cs.internal.useNet6", settingsMap.getOrDefault(OMNISHARP_USE_MODERN_NET, "true").toString());
294-
analyzerProperties.put("sonar.cs.internal.loadProjectOnDemand", settingsMap.getOrDefault(OMNISHARP_LOAD_PROJECT_ON_DEMAND, "false").toString());
295-
analyzerProperties.put("sonar.cs.internal.loadProjectsTimeout", settingsMap.getOrDefault(OMNISHARP_PROJECT_LOAD_TIMEOUT, "60").toString());
301+
analyzerProperties.put("sonar.cs.internal.useNet6", getStringValue(settingsMap, OMNISHARP_USE_MODERN_NET, "true"));
302+
analyzerProperties.put("sonar.cs.internal.loadProjectOnDemand", getStringValue(settingsMap, OMNISHARP_LOAD_PROJECT_ON_DEMAND, "false"));
303+
analyzerProperties.put("sonar.cs.internal.loadProjectsTimeout", getStringValue(settingsMap, OMNISHARP_PROJECT_LOAD_TIMEOUT, "60"));
296304
settingsMap.put(ANALYZER_PROPERTIES, analyzerProperties);
297305
settingsMap.put(ANALYSIS_EXCLUDES, addVscodeExcludesToSonarLintExcludes(analysisExcludes, settingsMap));
298306

299307
return settingsMap;
300308
}
301309

310+
private static String getStringValue(Map<String, Object> settingsMap, String key, String defaultValue) {
311+
String finalValue;
312+
try {
313+
var string = new Gson().fromJson((JsonElement) settingsMap.get(key), String.class);
314+
finalValue = string == null || string.isEmpty() ? defaultValue : string;
315+
} catch (JsonParseException e) {
316+
finalValue = defaultValue;
317+
}
318+
return finalValue;
319+
}
320+
302321
private static String addVscodeExcludesToSonarLintExcludes(String sonarLintExcludes, Map<String, Object> settingsMap) {
303322
var vscodeFilesExcludeMap = Utils.parseToMap(settingsMap.getOrDefault(VSCODE_FILE_EXCLUDES, new JsonObject()));
304323
var globPatterns = new StringBuilder();

src/test/java/org/sonarsource/sonarlint/ls/settings/SettingsManagerTests.java

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import com.google.gson.Gson;
2323
import com.google.gson.JsonElement;
24+
import com.google.gson.JsonNull;
2425
import com.google.gson.JsonObject;
2526
import com.google.gson.JsonPrimitive;
2627
import java.io.File;
@@ -731,10 +732,10 @@ void shouldUpdateAnalyzerProperties() {
731732
sonarLintSettings.add("disableTelemetry", new JsonPrimitive(false));
732733
sonarLintSettings.add("focusOnNewCode", new JsonPrimitive(true));
733734
Map<String, Object> settingsMap = new HashMap<>(Map.of(SONARLINT_CONFIGURATION_NAMESPACE, sonarLintSettings,
734-
DOTNET_DEFAULT_SOLUTION_PATH, "Roslyn.sln",
735-
OMNISHARP_USE_MODERN_NET, "true",
736-
OMNISHARP_LOAD_PROJECT_ON_DEMAND, "false",
737-
OMNISHARP_PROJECT_LOAD_TIMEOUT, "600"));
735+
DOTNET_DEFAULT_SOLUTION_PATH, new JsonPrimitive("Roslyn.sln"),
736+
OMNISHARP_USE_MODERN_NET, new JsonPrimitive("true"),
737+
OMNISHARP_LOAD_PROJECT_ON_DEMAND, new JsonPrimitive("false"),
738+
OMNISHARP_PROJECT_LOAD_TIMEOUT, new JsonPrimitive("600")));
738739

739740
var result = SettingsManager.updateProperties(workspaceUri, settingsMap);
740741

@@ -762,10 +763,10 @@ void shouldAddVSCodeExcludesInFileExclusions() {
762763
sonarLintSettings.add("disableTelemetry", new JsonPrimitive(false));
763764
sonarLintSettings.add("focusOnNewCode", new JsonPrimitive(true));
764765
Map<String, Object> settingsMap = new HashMap<>(Map.of(SONARLINT_CONFIGURATION_NAMESPACE, sonarLintSettings,
765-
DOTNET_DEFAULT_SOLUTION_PATH, "Roslyn.sln",
766-
OMNISHARP_USE_MODERN_NET, "true",
767-
OMNISHARP_LOAD_PROJECT_ON_DEMAND, "false",
768-
OMNISHARP_PROJECT_LOAD_TIMEOUT, "600",
766+
DOTNET_DEFAULT_SOLUTION_PATH, new JsonPrimitive("Roslyn.sln"),
767+
OMNISHARP_USE_MODERN_NET, new JsonPrimitive("true"),
768+
OMNISHARP_LOAD_PROJECT_ON_DEMAND, new JsonPrimitive("false"),
769+
OMNISHARP_PROJECT_LOAD_TIMEOUT, new JsonPrimitive("600"),
769770
VSCODE_FILE_EXCLUDES, vscodeExclusions));
770771

771772
var result = SettingsManager.updateProperties(workspaceUri, settingsMap);
@@ -823,6 +824,69 @@ void shouldNotNotifyAboutNodeJsChange() {
823824
verify(backendService, never()).didChangeClientNodeJsPath(any());
824825
}
825826

827+
@Test
828+
void shouldUpdatePropertiesWithDefaultValuesWhenNullSettings() {
829+
var workspaceUri = URI.create("file:///User/user/documents/project");
830+
var sonarLintSettings = new JsonObject();
831+
sonarLintSettings.add("disableTelemetry", new JsonPrimitive(false));
832+
sonarLintSettings.add("focusOnNewCode", new JsonPrimitive(true));
833+
Map<String, Object> settingsMap = new HashMap<>(Map.of(SONARLINT_CONFIGURATION_NAMESPACE, sonarLintSettings,
834+
DOTNET_DEFAULT_SOLUTION_PATH, JsonNull.INSTANCE,
835+
OMNISHARP_USE_MODERN_NET, JsonNull.INSTANCE,
836+
OMNISHARP_LOAD_PROJECT_ON_DEMAND, JsonNull.INSTANCE,
837+
OMNISHARP_PROJECT_LOAD_TIMEOUT, JsonNull.INSTANCE));
838+
839+
var result = SettingsManager.updateProperties(workspaceUri, settingsMap);
840+
841+
var analyzerProperties = (Map<String, String>) result.get(ANALYZER_PROPERTIES);
842+
assertThat(analyzerProperties).contains(entry("sonar.cs.internal.useNet6", "true"),
843+
entry("sonar.cs.internal.loadProjectOnDemand", "false"),
844+
entry("sonar.cs.internal.loadProjectsTimeout", "60"));
845+
assertThat(analyzerProperties.get("sonar.cs.internal.solutionPath")).isNull();
846+
}
847+
848+
@Test
849+
void shouldUpdatePropertiesWithDefaultValuesWhenEmptySettings() {
850+
var workspaceUri = URI.create("file:///User/user/documents/project");
851+
var sonarLintSettings = new JsonObject();
852+
sonarLintSettings.add("disableTelemetry", new JsonPrimitive(false));
853+
sonarLintSettings.add("focusOnNewCode", new JsonPrimitive(true));
854+
Map<String, Object> settingsMap = new HashMap<>(Map.of(SONARLINT_CONFIGURATION_NAMESPACE, sonarLintSettings,
855+
DOTNET_DEFAULT_SOLUTION_PATH, new JsonPrimitive(""),
856+
OMNISHARP_USE_MODERN_NET, new JsonPrimitive(""),
857+
OMNISHARP_LOAD_PROJECT_ON_DEMAND, new JsonPrimitive(""),
858+
OMNISHARP_PROJECT_LOAD_TIMEOUT, new JsonPrimitive("")));
859+
860+
var result = SettingsManager.updateProperties(workspaceUri, settingsMap);
861+
862+
var analyzerProperties = (Map<String, String>) result.get(ANALYZER_PROPERTIES);
863+
assertThat(analyzerProperties).contains(entry("sonar.cs.internal.useNet6", "true"),
864+
entry("sonar.cs.internal.loadProjectOnDemand", "false"),
865+
entry("sonar.cs.internal.loadProjectsTimeout", "60"));
866+
assertThat(analyzerProperties.get("sonar.cs.internal.solutionPath")).isNull();
867+
}
868+
869+
@Test
870+
void shouldUpdatePropertiesWithDefaultValuesWhenParsingFails() {
871+
var workspaceUri = URI.create("file:///User/user/documents/project");
872+
var sonarLintSettings = new JsonObject();
873+
sonarLintSettings.add("disableTelemetry", new JsonPrimitive(false));
874+
sonarLintSettings.add("focusOnNewCode", new JsonPrimitive(true));
875+
Map<String, Object> settingsMap = new HashMap<>(Map.of(SONARLINT_CONFIGURATION_NAMESPACE, sonarLintSettings,
876+
DOTNET_DEFAULT_SOLUTION_PATH, new JsonObject(),
877+
OMNISHARP_USE_MODERN_NET, new JsonObject(),
878+
OMNISHARP_LOAD_PROJECT_ON_DEMAND, new JsonObject(),
879+
OMNISHARP_PROJECT_LOAD_TIMEOUT, new JsonObject()));
880+
881+
var result = SettingsManager.updateProperties(workspaceUri, settingsMap);
882+
883+
var analyzerProperties = (Map<String, String>) result.get(ANALYZER_PROPERTIES);
884+
assertThat(analyzerProperties).contains(entry("sonar.cs.internal.useNet6", "true"),
885+
entry("sonar.cs.internal.loadProjectOnDemand", "false"),
886+
entry("sonar.cs.internal.loadProjectsTimeout", "60"));
887+
assertThat(analyzerProperties.get("sonar.cs.internal.solutionPath")).isNull();
888+
}
889+
826890
private static Map<String, Object> fromJsonString(String json) {
827891
return Utils.parseToMap(new Gson().fromJson(json, JsonElement.class));
828892
}

0 commit comments

Comments
 (0)