Skip to content

Commit

Permalink
Fix SSF-700
Browse files Browse the repository at this point in the history
  • Loading branch information
nquinquenel committed Jan 24, 2025
1 parent 782c922 commit 6cb35fd
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 163 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
public class StringUtils {

public static String pluralize(long count, String word) {
var pluralizedWord = count == 1 ? word : (word + 's');
var pluralizedWord = count == 1 || count == 0 ? word : (word + 's');
return count + " " + pluralizedWord;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* SonarLint Core - Commons
* Copyright (C) 2016-2025 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.core.commons;

import org.junit.jupiter.api.Test;
import org.sonarsource.sonarlint.core.commons.util.StringUtils;

import static org.assertj.core.api.Assertions.assertThat;

class StringUtilsTests {

@Test
void should_pluralize_words() {
assertThat(StringUtils.pluralize(0, "word")).isEqualTo("0 word");
assertThat(StringUtils.pluralize(1, "word")).isEqualTo("1 word");
assertThat(StringUtils.pluralize(2, "word")).isEqualTo("2 words");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import javax.annotation.Nullable;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpException;
Expand Down Expand Up @@ -128,8 +129,8 @@ public void handle(ClassicHttpRequest request, ClassicHttpResponse response, Htt
client.matchProjectBranch(new MatchProjectBranchParams(configScopeId, branchToMatch)).join().isBranchMatched();
if (!localBranchMatchesRequesting) {
client.showMessage(new ShowMessageParams(MessageType.ERROR,
"Attempted to show a fix suggestion from branch '" + branchToMatch + "', which is different from the currently " +
"checked-out branch.\nPlease switch to the correct branch and try again."));
"Attempted to show a fix suggestion from branch '" + StringEscapeUtils.escapeHtml(branchToMatch) + "', " +
"which is different from the currently checked-out branch.\nPlease switch to the correct branch and try again."));
return;
}

Expand All @@ -151,8 +152,8 @@ private boolean doesClientFileExists(String configScopeId, String filePath, Coll
if (optTranslation.isPresent()) {
var translation = optTranslation.get();
var idePath = translation.serverToIdePath(Paths.get(filePath));
for (var scope: boundScopes) {
for (var file: clientFs.getFiles(scope)) {
for (var scope : boundScopes) {
for (var file : clientFs.getFiles(scope)) {
if (Path.of(file.getUri()).endsWith(idePath)) {
return true;
}
Expand Down Expand Up @@ -180,7 +181,7 @@ private void showFixSuggestionForScope(String configScopeId, String issueKey, Fi
pathTranslationService.getOrComputePathTranslation(configScopeId).ifPresent(translation -> {
var fixSuggestionDto = new FixSuggestionDto(
fixSuggestion.suggestionId,
fixSuggestion.getExplanation(),
fixSuggestion.explanation(),
new FileEditDto(
translation.serverToIdePath(Paths.get(fixSuggestion.fileEdit.path)),
fixSuggestion.fileEdit.changes.stream().map(c ->
Expand Down Expand Up @@ -310,107 +311,45 @@ public FixSuggestionPayload getFixSuggestion() {
}

@VisibleForTesting
public static class FixSuggestionPayload {
private final FileEditPayload fileEdit;
private final String suggestionId;
private final String explanation;
public record FixSuggestionPayload(FileEditPayload fileEdit, String suggestionId, String explanation) {

public FixSuggestionPayload(FileEditPayload fileEdit, String suggestionId, String explanation) {
this.fileEdit = fileEdit;
this.suggestionId = suggestionId;
this.explanation = explanation;
this.explanation = StringEscapeUtils.escapeHtml(explanation);
}

public boolean isValid() {
return fileEdit.isValid() && !suggestionId.isBlank();
}

public FileEditPayload getFileEdit() {
return fileEdit;
}

public String getSuggestionId() {
return suggestionId;
}

public String getExplanation() {
return explanation;
}
}

@VisibleForTesting
public static class FileEditPayload {
private final List<ChangesPayload> changes;
private final String path;

public FileEditPayload(List<ChangesPayload> changes, String path) {
this.changes = changes;
this.path = path;
}
public record FileEditPayload(List<ChangesPayload> changes, String path) {

public boolean isValid() {
return !path.isBlank() && changes.stream().allMatch(ChangesPayload::isValid);
}

public List<ChangesPayload> getChanges() {
return changes;
}

public String getPath() {
return path;
}
}

@VisibleForTesting
public static class ChangesPayload {
private final TextRangePayload beforeLineRange;
private final String before;
private final String after;

public ChangesPayload(TextRangePayload beforeLineRange, String before, String after) {
this.beforeLineRange = beforeLineRange;
this.before = before;
this.after = after;
}
public record ChangesPayload(TextRangePayload beforeLineRange, String before, String after) {

public boolean isValid() {
return beforeLineRange.isValid();
}

public TextRangePayload getBeforeLineRange() {
return beforeLineRange;
}

public String getBefore() {
return before;
}

public String getAfter() {
return after;
}
}

@VisibleForTesting
public static class TextRangePayload {
private final int startLine;
private final int endLine;

public TextRangePayload(int startLine, int endLine) {
this.startLine = startLine;
this.endLine = endLine;
}
public record TextRangePayload(int startLine, int endLine) {

public boolean isValid() {
return startLine >= 0 && endLine >= 0 && startLine <= endLine;
}

public int getStartLine() {
return startLine;
}

public int getEndLine() {
return endLine;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,21 @@ public void handle(ClassicHttpRequest request, ClassicHttpResponse response, Htt
response.setEntity(new StringEntity("OK"));
}

private void showHotspotForScope(String connectionId, String configurationScopeId, String hotspotKey, SonarLintCancelMonitor cancelMonitor) {
private void showHotspotForScope(String connectionId, String configurationScopeId, String hotspotKey,
SonarLintCancelMonitor cancelMonitor) {
var hotspotOpt = tryFetchHotspot(connectionId, hotspotKey, cancelMonitor);
if (hotspotOpt.isPresent()) {
pathTranslationService.getOrComputePathTranslation(configurationScopeId)
.ifPresent(translation -> client.showHotspot(new ShowHotspotParams(configurationScopeId, adapt(hotspotKey, hotspotOpt.get(), translation))));
.ifPresent(translation -> client.showHotspot(new ShowHotspotParams(configurationScopeId, adapt(hotspotKey, hotspotOpt.get(),
translation))));
} else {
client.showMessage(new ShowMessageParams(MessageType.ERROR, "Could not show the hotspot. See logs for more details"));
}
}

private Optional<ServerHotspotDetails> tryFetchHotspot(String connectionId, String hotspotKey, SonarLintCancelMonitor cancelMonitor) {
return connectionManager.withValidConnectionFlatMapOptionalAndReturn(connectionId, api -> api.hotspot().fetch(hotspotKey, cancelMonitor));
return connectionManager.withValidConnectionFlatMapOptionalAndReturn(connectionId, api -> api.hotspot().fetch(hotspotKey,
cancelMonitor));
}

private static HotspotDetailsDto adapt(String hotspotKey, ServerHotspotDetails hotspot, FilePathTranslation translation) {
Expand Down Expand Up @@ -148,20 +151,12 @@ private static ShowHotspotQuery extractQuery(ClassicHttpRequest request) {
return new ShowHotspotQuery(params.get("server"), params.get("project"), params.get("hotspot"));
}

private static class ShowHotspotQuery {
private final String serverUrl;
private final String projectKey;
private final String hotspotKey;

private ShowHotspotQuery(String serverUrl, String projectKey, String hotspotKey) {
this.serverUrl = serverUrl;
this.projectKey = projectKey;
this.hotspotKey = hotspotKey;
}
private record ShowHotspotQuery(String serverUrl, String projectKey, String hotspotKey) {

public boolean isValid() {
return isNotBlank(serverUrl) && isNotBlank(projectKey) && isNotBlank(hotspotKey);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import javax.annotation.Nullable;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpException;
Expand Down Expand Up @@ -116,8 +117,9 @@ public void handle(ClassicHttpRequest request, ClassicHttpResponse response, Htt
}
var localBranchMatchesRequesting = client.matchProjectBranch(new MatchProjectBranchParams(configScopeId, branchToMatch)).join().isBranchMatched();
if (!localBranchMatchesRequesting) {
client.showMessage(new ShowMessageParams(MessageType.ERROR, "Attempted to show an issue from branch '" + branchToMatch + "', " +
"which is different from the currently checked-out branch.\nPlease switch to the correct branch and try again."));
client.showMessage(new ShowMessageParams(MessageType.ERROR, "Attempted to show an issue from branch " +
"'" + StringEscapeUtils.escapeHtml(branchToMatch) + "', which is different from the currently checked-out branch." +
"\nPlease switch to the correct branch and try again."));
return;
}
showIssueForScope(connectionId, configScopeId, showIssueQuery.issueKey, showIssueQuery.projectKey, branchToMatch,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,30 +87,9 @@ private boolean isTrustedServer(String serverOrigin) {
return repository.hasConnectionWithOrigin(serverOrigin);
}

private static class StatusResponse {
@Expose
private final String ideName;
@Expose
private final String description;
@Expose
private final boolean needsToken;
@Expose
private final CapabilitiesResponse capabilities;
private record StatusResponse(@Expose String ideName, @Expose String description, @Expose boolean needsToken,
@Expose CapabilitiesResponse capabilities) { }

public StatusResponse(String ideName, String description, boolean needsToken, CapabilitiesResponse capabilities) {
this.ideName = ideName;
this.description = description;
this.needsToken = needsToken;
this.capabilities = capabilities;
}
}

private static class CapabilitiesResponse {
@Expose
private final boolean canOpenFixSuggestion;
private record CapabilitiesResponse(@Expose boolean canOpenFixSuggestion) { }

public CapabilitiesResponse(boolean canOpenFixSuggestion) {
this.canOpenFixSuggestion = canOpenFixSuggestion;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,11 @@ public void onServerEventReceived(SonarServerEventReceivedEvent eventReceived) {
}

private void notifyClient(String connectionId, SmartNotificationEvent event) {
var projectKey = event.getProject();
var projectKey = event.project();
var boundScopes = configurationRepository.getBoundScopesToConnectionAndSonarProject(connectionId, projectKey);
client.showSmartNotification(new ShowSmartNotificationParams(event.getMessage(), event.getLink(),
boundScopes.stream().map(BoundScope::getConfigScopeId).collect(Collectors.toSet()), event.getCategory(), connectionId));
telemetryService.smartNotificationsReceived(event.getCategory());
client.showSmartNotification(new ShowSmartNotificationParams(event.message(), event.link(),
boundScopes.stream().map(BoundScope::getConfigScopeId).collect(Collectors.toSet()), event.category(), connectionId));
telemetryService.smartNotificationsReceived(event.category());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,18 @@
*/
package org.sonarsource.sonarlint.core.websocket.events;

import org.apache.commons.lang.StringEscapeUtils;
import org.sonarsource.sonarlint.core.serverapi.push.SonarServerEvent;

public class SmartNotificationEvent implements SonarServerEvent {

private final String message;
private final String link;
private final String project;
private final String date;
private final String category;
public record SmartNotificationEvent(String message, String link, String project, String date,
String category) implements SonarServerEvent {

public SmartNotificationEvent(String message, String link, String project, String date, String category) {
this.message = message;
this.message = StringEscapeUtils.escapeHtml(message);
this.link = link;
this.project = project;
this.date = date;
this.category = category;
}

public String getMessage() {
return message;
}

public String getLink() {
return link;
}

public String getProject() {
return project;
}

public String getDate() {
return date;
}

public String getCategory() {
return category;
}

}
Loading

0 comments on commit 6cb35fd

Please sign in to comment.