Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from SonarSource:master #206

Merged
merged 3 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

<properties>
<jdk.min.version>17</jdk.min.version>
<sonarlint.core.version>10.5.0.78949</sonarlint.core.version>
<sonarlint.core.version>10.6.0.79033</sonarlint.core.version>
<!-- Version used by Xodus -->
<kotlin.version>1.6.10</kotlin.version>
<!-- analyzers used for tests -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,12 @@ public void handleIssues(Map<URI, List<RaisedFindingDto>> issuesByFileUri) {
issuesCache.reportIssues(issuesByFileUri);
issuesByFileUri.forEach((uri, issues) -> {
diagnosticPublisher.publishDiagnostics(uri, true);
notebookDiagnosticPublisher.cleanupDiagnosticsForCellsWithoutIssues(uri);
openNotebooksCache.getFile(uri).ifPresent(notebook -> notebookDiagnosticPublisher.publishNotebookDiagnostics(uri, notebook));
openNotebooksCache.getFile(uri).ifPresent(notebook -> {
// clean up old diagnostics
notebookDiagnosticPublisher.cleanupCellsList(uri);
notebookDiagnosticPublisher.cleanupDiagnosticsForCellsWithoutIssues(uri);
notebookDiagnosticPublisher.publishNotebookDiagnostics(uri, notebook);
});
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import org.sonarsource.sonarlint.core.rpc.protocol.backend.tracking.TaintVulnerabilityDto;
import org.sonarsource.sonarlint.core.rpc.protocol.client.binding.AssistBindingParams;
import org.sonarsource.sonarlint.core.rpc.protocol.client.binding.AssistBindingResponse;
import org.sonarsource.sonarlint.core.rpc.protocol.client.binding.NoBindingSuggestionFoundParams;
import org.sonarsource.sonarlint.core.rpc.protocol.client.binding.SuggestBindingParams;
import org.sonarsource.sonarlint.core.rpc.protocol.client.connection.AssistCreatingConnectionParams;
import org.sonarsource.sonarlint.core.rpc.protocol.client.connection.AssistCreatingConnectionResponse;
Expand Down Expand Up @@ -311,9 +312,9 @@ public AssistBindingResponse assistBinding(AssistBindingParams params, SonarLint
}

@Override
public void noBindingSuggestionFound(String projectKey) {
public void noBindingSuggestionFound(NoBindingSuggestionFoundParams params) {
var messageRequestParams = new ShowMessageRequestParams();
messageRequestParams.setMessage("SonarLint couldn't match the server project '" + projectKey + "' to any of the currently " +
messageRequestParams.setMessage("SonarLint couldn't match the server project '" + params.getProjectKey() + "' to any of the currently " +
"open workspace folders. Please make sure the project is open in the workspace, or try configuring the binding manually.");
messageRequestParams.setType(MessageType.Error);
var learnMoreAction = new MessageActionItem("Learn more");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ public class VersionedOpenNotebook {

private final URI uri;
private Integer notebookVersion;
private Integer indexedNotebookVersion;
private final LinkedHashMap<String, TextDocumentItem> cells = new LinkedHashMap<>();
private final List<TextDocumentItem> orderedCells = new ArrayList<>();
private final Map<Integer, TextDocumentItem> fileLineToCell = new HashMap<>();
Expand All @@ -69,9 +68,6 @@ private VersionedOpenNotebook(URI uri, int version, List<TextDocumentItem> cells
}

private void indexCellsByLineNumber() {
if (notebookVersion.equals(indexedNotebookVersion)) {
return;
}
var lineCount = 1;
var cellCount = 1;
for (var cell : orderedCells) {
Expand All @@ -88,7 +84,6 @@ private void indexCellsByLineNumber() {
}
cellCount++;
}
indexedNotebookVersion = notebookVersion;
}

public static VersionedOpenNotebook create(URI baseUri, int version, List<TextDocumentItem> cells, NotebookDiagnosticPublisher notebookDiagnosticPublisher) {
Expand Down Expand Up @@ -117,7 +112,6 @@ public Set<String> getCellUris() {
}

public Optional<URI> getCellUri(int lineNumber) {
indexCellsByLineNumber();
return Optional.ofNullable(fileLineToCell.get(lineNumber))
.map(TextDocumentItem::getUri)
.map(URI::create);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,11 @@ public static String softwareQualityToLabel(SoftwareQuality softwareQuality) {

public static String impactSeverityToLabel(ImpactSeverity softwareQuality) {
return switch (softwareQuality) {
case INFO -> "Info";
case LOW -> "Low";
case MEDIUM -> "Medium";
case HIGH -> "High";
case BLOCKER -> "Blocker";
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
import org.sonarsource.sonarlint.core.rpc.protocol.backend.tracking.TextRangeWithHashDto;
import org.sonarsource.sonarlint.core.rpc.protocol.client.OpenUrlInBrowserParams;
import org.sonarsource.sonarlint.core.rpc.protocol.client.binding.AssistBindingParams;
import org.sonarsource.sonarlint.core.rpc.protocol.client.binding.NoBindingSuggestionFoundParams;
import org.sonarsource.sonarlint.core.rpc.protocol.client.binding.SuggestBindingParams;
import org.sonarsource.sonarlint.core.rpc.protocol.client.connection.AssistCreatingConnectionParams;
import org.sonarsource.sonarlint.core.rpc.protocol.client.connection.ConnectionSuggestionDto;
Expand Down Expand Up @@ -533,7 +534,7 @@ void testNoBindingSuggestionFound() {
var learnMoreAction = new MessageActionItem("Learn more");
messageRequestParams.setActions(List.of(learnMoreAction));

underTest.noBindingSuggestionFound(projectKey);
underTest.noBindingSuggestionFound(new NoBindingSuggestionFoundParams(projectKey, false));
verify(client).showMessageRequest(messageRequestParams);
verify(client).browseTo("https://docs.sonarsource.com/sonarlint/vs-code/troubleshooting/#troubleshooting-connected-mode-setup");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
package org.sonarsource.sonarlint.ls.notebooks;

import java.net.URI;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;
import org.eclipse.lsp4j.NotebookCellArrayChange;
import org.eclipse.lsp4j.NotebookDocumentChangeEvent;
Expand All @@ -40,10 +42,14 @@
import org.sonarsource.sonarlint.core.rpc.protocol.client.issue.IssueFlowDto;
import org.sonarsource.sonarlint.core.rpc.protocol.client.issue.QuickFixDto;
import org.sonarsource.sonarlint.core.rpc.protocol.client.issue.RaisedFindingDto;
import org.sonarsource.sonarlint.core.rpc.protocol.client.issue.RaisedIssueDto;
import org.sonarsource.sonarlint.core.rpc.protocol.client.issue.TextEditDto;
import org.sonarsource.sonarlint.core.rpc.protocol.common.CleanCodeAttribute;
import org.sonarsource.sonarlint.core.rpc.protocol.common.IssueSeverity;
import org.sonarsource.sonarlint.core.rpc.protocol.common.RuleType;
import org.sonarsource.sonarlint.core.rpc.protocol.common.TextRangeDto;
import org.sonarsource.sonarlint.ls.connected.DelegatingFinding;
import org.sonarsource.sonarlint.ls.connected.DelegatingIssue;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -110,6 +116,8 @@ void shouldCorrectlyMapFileLineToCellLine() {
var tmpUri = URI.create("file:///some/notebook.ipynb");
var underTest = createTestNotebookWithThreeCells(tmpUri);

manuallyReindexCellLines(underTest);

assertThat(underTest.getCellUri(1)).contains(URI.create(tmpUri + "#cell1"));
assertThat(underTest.getCellUri(2)).contains(URI.create(tmpUri + "#cell1"));
assertThat(underTest.getCellUri(3)).contains(URI.create(tmpUri + "#cell1"));
Expand Down Expand Up @@ -173,6 +181,8 @@ void shouldConvertQuickFixWithSingleFileEdit() {
var fakeNotebook = createTestNotebookWithThreeCells(tmpUri);
var quickFixTextRange = new TextRangeDto(9, 0, 9, 2);

manuallyReindexCellLines(fakeNotebook);

var textEdit = mock(TextEditDto.class);
when(textEdit.newText()).thenReturn("");
when(textEdit.range()).thenReturn(quickFixTextRange);
Expand Down Expand Up @@ -211,6 +221,8 @@ void shouldConvertQuickFixWithMultipleFileEdits() {
var quickFixTextRange1 = new TextRangeDto(9, 0, 9, 2);
var quickFixTextRange2 = new TextRangeDto(5, 0, 6, 2);

manuallyReindexCellLines(fakeNotebook);

var textEdit1 = mock(org.sonarsource.sonarlint.core.rpc.protocol.client.issue.TextEditDto.class);
when(textEdit1.newText()).thenReturn("");
when(textEdit1.range()).thenReturn(quickFixTextRange1);
Expand Down Expand Up @@ -308,6 +320,8 @@ void shouldHandleCellCreation() {

underTest.didChange(2, changeEvent);

manuallyReindexCellLines(underTest);

assertThat(underTest.getNotebookVersion()).isEqualTo(2);
assertThat(underTest.getCellUris()).hasSize(4);
assertThat(underTest.getContent()).isEqualTo("" +
Expand Down Expand Up @@ -350,6 +364,8 @@ void shouldHandleCellDeletion() {

underTest.didChange(2, changeEvent);

manuallyReindexCellLines(underTest);

assertThat(underTest.getNotebookVersion()).isEqualTo(2);
assertThat(underTest.getCellUris()).hasSize(2);
assertThat(underTest.getContent()).isEqualTo("" +
Expand Down Expand Up @@ -382,6 +398,7 @@ void shouldNotFailWhenRemovingNonexistentCell() {
changeEvent.setCells(changeEventCells);

underTest.didChange(2, changeEvent);
manuallyReindexCellLines(underTest);

assertThat(underTest.getNotebookVersion()).isEqualTo(2);
assertThat(underTest.getCellUris()).hasSize(3);
Expand Down Expand Up @@ -494,4 +511,25 @@ public static VersionedOpenNotebook createTestNotebookWithThreeCells(URI tmpUri)
return VersionedOpenNotebook.create(tmpUri, 1, List.of(cell1, cell2, cell3), mock(NotebookDiagnosticPublisher.class));
}

private void manuallyReindexCellLines(VersionedOpenNotebook underTest) {
var fakeFindingDto = new RaisedIssueDto(
UUID.randomUUID(),
null,
"ruleKey",
"message",
IssueSeverity.BLOCKER,
RuleType.BUG,
CleanCodeAttribute.TRUSTWORTHY,
List.of(),
Instant.now(),
true,
false,
new TextRangeDto(1, 0, 1, 0),
List.of(),
List.of(),
null
);
underTest.toCellIssue(new DelegatingIssue(fakeFindingDto, URI.create("")));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,72 +19,92 @@
*/
package org.sonarsource.sonarlint.ls.util;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.sonarsource.sonarlint.core.rpc.protocol.backend.issue.ResolutionStatus;
import org.sonarsource.sonarlint.core.rpc.protocol.common.CleanCodeAttribute;
import org.sonarsource.sonarlint.core.rpc.protocol.common.CleanCodeAttributeCategory;
import org.sonarsource.sonarlint.core.rpc.protocol.common.ImpactSeverity;
import org.sonarsource.sonarlint.core.rpc.protocol.common.SoftwareQuality;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class EnumLabelsMapperTests {

@Test
void resolutionStatusToLabel() {
assertThat(EnumLabelsMapper.resolutionStatusToLabel(ResolutionStatus.ACCEPT)).isEqualTo("Accepted");
assertThat(EnumLabelsMapper.resolutionStatusToLabel(ResolutionStatus.FALSE_POSITIVE)).isEqualTo("False positive");
assertThat(EnumLabelsMapper.resolutionStatusToLabel(ResolutionStatus.WONT_FIX)).isEqualTo("Won't fix");
@ParameterizedTest(name = "ResolutionStatus.{0} is mapped to `{1}`")
@CsvSource({
"ACCEPT , Accepted",
"FALSE_POSITIVE, False positive",
"WONT_FIX , Won't fix",
})
void resolutionStatusToLabel(String enumName, String expectedLabel) {
assertThat(EnumLabelsMapper.resolutionStatusToLabel(ResolutionStatus.valueOf(enumName))).isEqualTo(expectedLabel);
}

@Test
void resolutionStatusFromLabel() {
assertThat(EnumLabelsMapper.resolutionStatusFromLabel("Accepted")).isEqualTo(ResolutionStatus.ACCEPT);
assertThat(EnumLabelsMapper.resolutionStatusFromLabel("False positive")).isEqualTo(ResolutionStatus.FALSE_POSITIVE);
assertThat(EnumLabelsMapper.resolutionStatusFromLabel("Won't fix")).isEqualTo(ResolutionStatus.WONT_FIX);
assertThrows(IllegalArgumentException.class, () -> EnumLabelsMapper.resolutionStatusFromLabel("Unknown"));
@ParameterizedTest(name = "Label `{0}` is mapped to ResolutionStatus.{1}")
@CsvSource({
"Accepted , ACCEPT",
"False positive, FALSE_POSITIVE",
"Won't fix , WONT_FIX",
})
void resolutionStatusFromLabel(String label, String expectedEnumValue) {
assertThat(EnumLabelsMapper.resolutionStatusFromLabel(label)).isEqualTo(ResolutionStatus.valueOf(expectedEnumValue));
assertThatThrownBy(() -> EnumLabelsMapper.resolutionStatusFromLabel("Unknown")).isInstanceOf(IllegalArgumentException.class);
}

@Test
void cleanCodeAttributeToLabel() {
assertEquals("Not conventional", EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.CONVENTIONAL));
assertEquals("Not formatted", EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.FORMATTED));
assertEquals("Not identifiable", EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.IDENTIFIABLE));
assertEquals("Not clear", EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.CLEAR));
assertEquals("Not complete", EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.COMPLETE));
assertEquals("Not efficient", EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.EFFICIENT));
assertEquals("Not logical", EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.LOGICAL));
assertEquals("Not distinct", EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.DISTINCT));
assertEquals("Not focused", EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.FOCUSED));
assertEquals("Not modular", EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.MODULAR));
assertEquals("Not tested", EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.TESTED));
assertEquals("Not lawful", EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.LAWFUL));
assertEquals("Not respectful", EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.RESPECTFUL));
assertEquals("Not trustworthy", EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.TRUSTWORTHY));
@ParameterizedTest(name = "CleanCodeAttribute.{0} is mapped to `{1}`")
@CsvSource({
"CONVENTIONAL, Not conventional",
"FORMATTED , Not formatted",
"IDENTIFIABLE, Not identifiable",
"CLEAR , Not clear",
"COMPLETE , Not complete",
"EFFICIENT , Not efficient",
"LOGICAL , Not logical",
"DISTINCT , Not distinct",
"FOCUSED , Not focused",
"MODULAR , Not modular",
"TESTED , Not tested",
"LAWFUL , Not lawful",
"RESPECTFUL , Not respectful",
"TRUSTWORTHY , Not trustworthy"
})
void cleanCodeAttributeToLabel(String enumName, String expectedLabel) {
assertThat(EnumLabelsMapper.cleanCodeAttributeToLabel(CleanCodeAttribute.valueOf(enumName))).isEqualTo(expectedLabel);
}

@Test
void testCleanCodeAttributeCategoryToLabel() {
assertEquals("Adaptability", EnumLabelsMapper.cleanCodeAttributeCategoryToLabel(CleanCodeAttributeCategory.ADAPTABLE));
assertEquals("Consistency", EnumLabelsMapper.cleanCodeAttributeCategoryToLabel(CleanCodeAttributeCategory.CONSISTENT));
assertEquals("Intentionality", EnumLabelsMapper.cleanCodeAttributeCategoryToLabel(CleanCodeAttributeCategory.INTENTIONAL));
assertEquals("Responsibility", EnumLabelsMapper.cleanCodeAttributeCategoryToLabel(CleanCodeAttributeCategory.RESPONSIBLE));
@ParameterizedTest(name = "CleanCodeAttributeCategory.{0} is mapped to `{1}`")
@CsvSource({
"ADAPTABLE , Adaptability",
"CONSISTENT , Consistency",
"INTENTIONAL, Intentionality",
"RESPONSIBLE, Responsibility"
})
void testCleanCodeAttributeCategoryToLabel(String enumName, String expectedLabel) {
assertThat(EnumLabelsMapper.cleanCodeAttributeCategoryToLabel(CleanCodeAttributeCategory.valueOf(enumName))).isEqualTo(expectedLabel);
}

@Test
void testSoftwareQualityToLabel() {
assertEquals("Maintainability", EnumLabelsMapper.softwareQualityToLabel(SoftwareQuality.MAINTAINABILITY));
assertEquals("Reliability", EnumLabelsMapper.softwareQualityToLabel(SoftwareQuality.RELIABILITY));
assertEquals("Security", EnumLabelsMapper.softwareQualityToLabel(SoftwareQuality.SECURITY));
@ParameterizedTest(name = "SoftwareQuality.{0} is mapped to `{1}`")
@CsvSource({
"MAINTAINABILITY, Maintainability",
"RELIABILITY , Reliability",
"SECURITY , Security"
})
void testSoftwareQualityToLabel(String enumName, String expectedLabel) {
assertThat(EnumLabelsMapper.softwareQualityToLabel(SoftwareQuality.valueOf(enumName))).isEqualTo(expectedLabel);
}

@Test
void testImpactSeverityToLabel() {
assertEquals("Low", EnumLabelsMapper.impactSeverityToLabel(ImpactSeverity.LOW));
assertEquals("Medium", EnumLabelsMapper.impactSeverityToLabel(ImpactSeverity.MEDIUM));
assertEquals("High", EnumLabelsMapper.impactSeverityToLabel(ImpactSeverity.HIGH));
@ParameterizedTest(name = "ImpactSeverity.{0} is mapped to `{1}`")
@CsvSource({
"INFO , Info",
"LOW , Low",
"MEDIUM , Medium",
"HIGH , High",
"BLOCKER, Blocker",
})
void testImpactSeverityToLabel(String enumName, String expectedLabel) {
assertThat(EnumLabelsMapper.impactSeverityToLabel(ImpactSeverity.valueOf(enumName))).isEqualTo(expectedLabel);
}

}