Skip to content

Commit

Permalink
SLLS-266 correctly handle JSON values in settings
Browse files Browse the repository at this point in the history
  • Loading branch information
sophio-japharidze-sonarsource committed Sep 25, 2024
1 parent b973712 commit 00df27b
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@
package org.sonarsource.sonarlint.ls.settings;

import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import java.net.URI;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
Expand Down Expand Up @@ -281,24 +285,39 @@ static Map<String, Object> updateProperties(@org.jetbrains.annotations.Nullable
var analyzerProperties = (Map<String, String>) (sonarLintSettingsMap == null ?
Maps.newHashMap() :
sonarLintSettingsMap.getOrDefault(ANALYZER_PROPERTIES, Maps.newHashMap()));
var analysisExcludes = (String) settingsMap.getOrDefault(ANALYSIS_EXCLUDES, "");
var analysisExcludes = getStringValue(settingsMap, ANALYSIS_EXCLUDES, "");
forceIgnoreRazorFiles(analyzerProperties);
var solutionRelativePath = settingsMap.getOrDefault(DOTNET_DEFAULT_SOLUTION_PATH, "").toString();
var solutionRelativePath = getStringValue(settingsMap, DOTNET_DEFAULT_SOLUTION_PATH, "");
if (!solutionRelativePath.isEmpty() && workspaceUri != null) {
// uri: file:///Users/me/Documents/Sonar/roslyn
// solutionPath: Roslyn.sln
// we want: /Users/me/Documents/Sonar/roslyn/Roslyn.sln
analyzerProperties.put("sonar.cs.internal.solutionPath", Path.of(workspaceUri).resolve(solutionRelativePath).toAbsolutePath().toString());
try {
analyzerProperties.put("sonar.cs.internal.solutionPath", Path.of(workspaceUri).resolve(solutionRelativePath).toAbsolutePath().toString());
} catch (InvalidPathException e) {
analyzerProperties.put("sonar.cs.internal.solutionPath", "");
}
}
analyzerProperties.put("sonar.cs.internal.useNet6", settingsMap.getOrDefault(OMNISHARP_USE_MODERN_NET, "true").toString());
analyzerProperties.put("sonar.cs.internal.loadProjectOnDemand", settingsMap.getOrDefault(OMNISHARP_LOAD_PROJECT_ON_DEMAND, "false").toString());
analyzerProperties.put("sonar.cs.internal.loadProjectsTimeout", settingsMap.getOrDefault(OMNISHARP_PROJECT_LOAD_TIMEOUT, "60").toString());
analyzerProperties.put("sonar.cs.internal.useNet6", getStringValue(settingsMap, OMNISHARP_USE_MODERN_NET, "true"));
analyzerProperties.put("sonar.cs.internal.loadProjectOnDemand", getStringValue(settingsMap, OMNISHARP_LOAD_PROJECT_ON_DEMAND, "false"));
analyzerProperties.put("sonar.cs.internal.loadProjectsTimeout", getStringValue(settingsMap, OMNISHARP_PROJECT_LOAD_TIMEOUT, "60"));
settingsMap.put(ANALYZER_PROPERTIES, analyzerProperties);
settingsMap.put(ANALYSIS_EXCLUDES, addVscodeExcludesToSonarLintExcludes(analysisExcludes, settingsMap));

return settingsMap;
}

private static String getStringValue(Map<String, Object> settingsMap, String key, String defaultValue) {
String finalValue;
try {
var string = new Gson().fromJson((JsonElement) settingsMap.get(key), String.class);
finalValue = string == null || string.isEmpty() ? defaultValue : string;
} catch (JsonParseException e) {
finalValue = defaultValue;
}
return finalValue;
}

private static String addVscodeExcludesToSonarLintExcludes(String sonarLintExcludes, Map<String, Object> settingsMap) {
var vscodeFilesExcludeMap = Utils.parseToMap(settingsMap.getOrDefault(VSCODE_FILE_EXCLUDES, new JsonObject()));
var globPatterns = new StringBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import java.io.File;
Expand Down Expand Up @@ -731,10 +732,10 @@ void shouldUpdateAnalyzerProperties() {
sonarLintSettings.add("disableTelemetry", new JsonPrimitive(false));
sonarLintSettings.add("focusOnNewCode", new JsonPrimitive(true));
Map<String, Object> settingsMap = new HashMap<>(Map.of(SONARLINT_CONFIGURATION_NAMESPACE, sonarLintSettings,
DOTNET_DEFAULT_SOLUTION_PATH, "Roslyn.sln",
OMNISHARP_USE_MODERN_NET, "true",
OMNISHARP_LOAD_PROJECT_ON_DEMAND, "false",
OMNISHARP_PROJECT_LOAD_TIMEOUT, "600"));
DOTNET_DEFAULT_SOLUTION_PATH, new JsonPrimitive("Roslyn.sln"),
OMNISHARP_USE_MODERN_NET, new JsonPrimitive("true"),
OMNISHARP_LOAD_PROJECT_ON_DEMAND, new JsonPrimitive("false"),
OMNISHARP_PROJECT_LOAD_TIMEOUT, new JsonPrimitive("600")));

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

Expand Down Expand Up @@ -762,10 +763,10 @@ void shouldAddVSCodeExcludesInFileExclusions() {
sonarLintSettings.add("disableTelemetry", new JsonPrimitive(false));
sonarLintSettings.add("focusOnNewCode", new JsonPrimitive(true));
Map<String, Object> settingsMap = new HashMap<>(Map.of(SONARLINT_CONFIGURATION_NAMESPACE, sonarLintSettings,
DOTNET_DEFAULT_SOLUTION_PATH, "Roslyn.sln",
OMNISHARP_USE_MODERN_NET, "true",
OMNISHARP_LOAD_PROJECT_ON_DEMAND, "false",
OMNISHARP_PROJECT_LOAD_TIMEOUT, "600",
DOTNET_DEFAULT_SOLUTION_PATH, new JsonPrimitive("Roslyn.sln"),
OMNISHARP_USE_MODERN_NET, new JsonPrimitive("true"),
OMNISHARP_LOAD_PROJECT_ON_DEMAND, new JsonPrimitive("false"),
OMNISHARP_PROJECT_LOAD_TIMEOUT, new JsonPrimitive("600"),
VSCODE_FILE_EXCLUDES, vscodeExclusions));

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

@Test
void shouldUpdatePropertiesWithDefaultValuesWhenNullSettings() {
var workspaceUri = URI.create("file:///User/user/documents/project");
var sonarLintSettings = new JsonObject();
sonarLintSettings.add("disableTelemetry", new JsonPrimitive(false));
sonarLintSettings.add("focusOnNewCode", new JsonPrimitive(true));
Map<String, Object> settingsMap = new HashMap<>(Map.of(SONARLINT_CONFIGURATION_NAMESPACE, sonarLintSettings,
DOTNET_DEFAULT_SOLUTION_PATH, JsonNull.INSTANCE,
OMNISHARP_USE_MODERN_NET, JsonNull.INSTANCE,
OMNISHARP_LOAD_PROJECT_ON_DEMAND, JsonNull.INSTANCE,
OMNISHARP_PROJECT_LOAD_TIMEOUT, JsonNull.INSTANCE));

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

var analyzerProperties = (Map<String, String>) result.get(ANALYZER_PROPERTIES);
assertThat(analyzerProperties).contains(entry("sonar.cs.internal.useNet6", "true"),
entry("sonar.cs.internal.loadProjectOnDemand", "false"),
entry("sonar.cs.internal.loadProjectsTimeout", "60"));
assertThat(analyzerProperties.get("sonar.cs.internal.solutionPath")).isNull();
}

@Test
void shouldUpdatePropertiesWithDefaultValuesWhenEmptySettings() {
var workspaceUri = URI.create("file:///User/user/documents/project");
var sonarLintSettings = new JsonObject();
sonarLintSettings.add("disableTelemetry", new JsonPrimitive(false));
sonarLintSettings.add("focusOnNewCode", new JsonPrimitive(true));
Map<String, Object> settingsMap = new HashMap<>(Map.of(SONARLINT_CONFIGURATION_NAMESPACE, sonarLintSettings,
DOTNET_DEFAULT_SOLUTION_PATH, new JsonPrimitive(""),
OMNISHARP_USE_MODERN_NET, new JsonPrimitive(""),
OMNISHARP_LOAD_PROJECT_ON_DEMAND, new JsonPrimitive(""),
OMNISHARP_PROJECT_LOAD_TIMEOUT, new JsonPrimitive("")));

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

var analyzerProperties = (Map<String, String>) result.get(ANALYZER_PROPERTIES);
assertThat(analyzerProperties).contains(entry("sonar.cs.internal.useNet6", "true"),
entry("sonar.cs.internal.loadProjectOnDemand", "false"),
entry("sonar.cs.internal.loadProjectsTimeout", "60"));
assertThat(analyzerProperties.get("sonar.cs.internal.solutionPath")).isNull();
}

@Test
void shouldUpdatePropertiesWithDefaultValuesWhenParsingFails() {
var workspaceUri = URI.create("file:///User/user/documents/project");
var sonarLintSettings = new JsonObject();
sonarLintSettings.add("disableTelemetry", new JsonPrimitive(false));
sonarLintSettings.add("focusOnNewCode", new JsonPrimitive(true));
Map<String, Object> settingsMap = new HashMap<>(Map.of(SONARLINT_CONFIGURATION_NAMESPACE, sonarLintSettings,
DOTNET_DEFAULT_SOLUTION_PATH, new JsonObject(),
OMNISHARP_USE_MODERN_NET, new JsonObject(),
OMNISHARP_LOAD_PROJECT_ON_DEMAND, new JsonObject(),
OMNISHARP_PROJECT_LOAD_TIMEOUT, new JsonObject()));

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

var analyzerProperties = (Map<String, String>) result.get(ANALYZER_PROPERTIES);
assertThat(analyzerProperties).contains(entry("sonar.cs.internal.useNet6", "true"),
entry("sonar.cs.internal.loadProjectOnDemand", "false"),
entry("sonar.cs.internal.loadProjectsTimeout", "60"));
assertThat(analyzerProperties.get("sonar.cs.internal.solutionPath")).isNull();
}

private static Map<String, Object> fromJsonString(String json) {
return Utils.parseToMap(new Gson().fromJson(json, JsonElement.class));
}
Expand Down

0 comments on commit 00df27b

Please sign in to comment.