Skip to content

Commit

Permalink
SLI-1657 Allow displaying both standard and MQR rule descriptions (#1211
Browse files Browse the repository at this point in the history
)
  • Loading branch information
nquinquenel authored Nov 5, 2024
1 parent 87e5aa0 commit 9aa4dbd
Show file tree
Hide file tree
Showing 51 changed files with 753 additions and 334 deletions.
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[versions]
sonarlint-core = "10.7.1.79146"
sonarlint-core = "10.9.0.79477"

sonar-java = "8.5.0.37199"
sonar-javascript = "10.16.0.27621"
Expand Down
103 changes: 84 additions & 19 deletions src/main/java/org/sonarlint/intellij/SonarLintIcons.kt
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,42 @@ object SonarLintIcons {
@JvmField
val FOCUS = getIcon("/images/focus.svg")

private val BUG_ICONS = mapOf(
IssueSeverity.BLOCKER to getIcon("/images/bug/bugBlocker.svg"),
IssueSeverity.CRITICAL to getIcon("/images/bug/bugHigh.svg"),
IssueSeverity.MAJOR to getIcon("/images/bug/bugMedium.svg"),
IssueSeverity.MINOR to getIcon("/images/bug/bugLow.svg"),
IssueSeverity.INFO to getIcon("/images/bug/bugInfo.svg")
)

private val CODE_SMELL_ICONS = mapOf(
IssueSeverity.BLOCKER to getIcon("/images/codeSmell/codeSmellBlocker.svg"),
IssueSeverity.CRITICAL to getIcon("/images/codeSmell/codeSmellHigh.svg"),
IssueSeverity.MAJOR to getIcon("/images/codeSmell/codeSmellMedium.svg"),
IssueSeverity.MINOR to getIcon("/images/codeSmell/codeSmellLow.svg"),
IssueSeverity.INFO to getIcon("/images/codeSmell/codeSmellInfo.svg")
)

private val VULNERABILITY_ICONS = mapOf(
IssueSeverity.BLOCKER to getIcon("/images/vulnerability/vulnerabilityBlocker.svg"),
IssueSeverity.CRITICAL to getIcon("/images/vulnerability/vulnerabilityHigh.svg"),
IssueSeverity.MAJOR to getIcon("/images/vulnerability/vulnerabilityMedium.svg"),
IssueSeverity.MINOR to getIcon("/images/vulnerability/vulnerabilityLow.svg"),
IssueSeverity.INFO to getIcon("/images/vulnerability/vulnerabilityInfo.svg")
)

private val PROBABILITY_ICONS = mapOf(
VulnerabilityProbability.HIGH to getIcon("/images/hotspot/hotspotHigh.svg"),
VulnerabilityProbability.MEDIUM to getIcon("/images/hotspot/hotspotMedium.svg"),
VulnerabilityProbability.LOW to getIcon("/images/hotspot/hotspotLow.svg")
)

private val SEVERITY_ICONS = mapOf(
IssueSeverity.BLOCKER to getIcon("/images/severity/blocker.svg"),
IssueSeverity.CRITICAL to getIcon("/images/severity/critical.svg"),
IssueSeverity.INFO to getIcon("/images/severity/info.svg"),
IssueSeverity.MAJOR to getIcon("/images/severity/major.svg"),
IssueSeverity.MINOR to getIcon("/images/severity/minor.svg")
IssueSeverity.BLOCKER to getIcon("/images/impact/blocker.svg"),
IssueSeverity.CRITICAL to getIcon("/images/impact/high.svg"),
IssueSeverity.MAJOR to getIcon("/images/impact/medium.svg"),
IssueSeverity.MINOR to getIcon("/images/impact/low.svg"),
IssueSeverity.INFO to getIcon("/images/impact/info.svg")
)

private val IMPACT_ICONS = mapOf(
Expand All @@ -98,17 +128,46 @@ object SonarLintIcons {
ImpactSeverity.INFO to getIcon("/images/impact/info.svg")
)

private val TYPE_ICONS = mapOf(
RuleType.BUG to getIcon("/images/type/bug.svg"),
RuleType.CODE_SMELL to getIcon("/images/type/codeSmell.svg"),
RuleType.VULNERABILITY to getIcon("/images/type/vulnerability.svg"),
RuleType.SECURITY_HOTSPOT to getIcon("/images/type/hotspot.svg")
val backgroundColorsByVulnerabilityProbability = mapOf(
VulnerabilityProbability.HIGH to JBColor(Color(254, 243, 242), Color(253, 162, 155, 20)),
VulnerabilityProbability.MEDIUM to JBColor(Color(255, 240, 235), Color(254, 150, 75, 20)),
VulnerabilityProbability.LOW to JBColor(Color(252, 245, 228), Color(250, 220, 121, 20))
)

private val PROBABILITY_ICONS = mapOf(
VulnerabilityProbability.HIGH to getIcon("/images/type/hotspotHigh.svg"),
VulnerabilityProbability.MEDIUM to getIcon("/images/type/hotspotMedium.svg"),
VulnerabilityProbability.LOW to getIcon("/images/type/hotspotLow.svg")
val fontColorsByVulnerabilityProbability = mapOf(
VulnerabilityProbability.HIGH to JBColor(Color(180, 35, 24), Color(253, 162, 155)),
VulnerabilityProbability.MEDIUM to JBColor(Color(147, 55, 13), Color(254, 150, 75)),
VulnerabilityProbability.LOW to JBColor(Color(140, 94, 30), Color(250, 220, 121))
)

val borderColorsByVulnerabilityProbability = mapOf(
VulnerabilityProbability.HIGH to JBColor(Color(217, 44, 32), Color(253, 162, 155)),
VulnerabilityProbability.MEDIUM to JBColor(Color(254, 150, 75), Color(254, 150, 75)),
VulnerabilityProbability.LOW to JBColor(Color(250, 220, 121), Color(250, 220, 121))
)

val backgroundColorsBySeverity = mapOf(
IssueSeverity.BLOCKER to JBColor(Color(254, 228, 226), Color(128, 27, 20, 20)),
IssueSeverity.CRITICAL to JBColor(Color(254, 243, 242), Color(253, 162, 155, 20)),
IssueSeverity.MAJOR to JBColor(Color(255, 240, 235), Color(254, 150, 75, 20)),
IssueSeverity.MINOR to JBColor(Color(252, 245, 228), Color(250, 220, 121, 20)),
IssueSeverity.INFO to JBColor(Color(245, 251, 255), Color(143, 202, 234, 20))
)

val fontColorsBySeverity = mapOf(
IssueSeverity.BLOCKER to JBColor(Color(128, 27, 20), Color(249, 112, 102)),
IssueSeverity.CRITICAL to JBColor(Color(180, 35, 24), Color(253, 162, 155)),
IssueSeverity.MAJOR to JBColor(Color(147, 55, 13), Color(254, 150, 75)),
IssueSeverity.MINOR to JBColor(Color(140, 94, 30), Color(250, 220, 121)),
IssueSeverity.INFO to JBColor(Color(49, 107, 146), Color(143, 202, 234))
)

val borderColorsBySeverity = mapOf(
IssueSeverity.BLOCKER to JBColor(Color(128, 27, 20), Color(249, 112, 102)),
IssueSeverity.CRITICAL to JBColor(Color(217, 44, 32), Color(253, 162, 155)),
IssueSeverity.MAJOR to JBColor(Color(254, 150, 75), Color(254, 150, 75)),
IssueSeverity.MINOR to JBColor(Color(250, 220, 121), Color(250, 220, 121)),
IssueSeverity.INFO to JBColor(Color(143, 202, 234), Color(143, 202, 234))
)

val backgroundColorsByImpact = mapOf(
Expand Down Expand Up @@ -144,11 +203,6 @@ object SonarLintIcons {
return SEVERITY_ICONS[severity]!!
}

@JvmStatic
fun type(type: RuleType): Icon {
return TYPE_ICONS[type]!!
}

@JvmStatic
fun impact(impact: ImpactSeverity): Icon {
return IMPACT_ICONS[impact]!!
Expand All @@ -163,4 +217,15 @@ object SonarLintIcons {
fun hotspotTypeWithProbability(vulnerabilityProbability: VulnerabilityProbability): Icon {
return PROBABILITY_ICONS[vulnerabilityProbability]!!
}

@JvmStatic
fun getIconForTypeAndSeverity(type: RuleType, severity: IssueSeverity): Icon {
return when (type) {
RuleType.BUG -> BUG_ICONS[severity]!!
RuleType.CODE_SMELL -> CODE_SMELL_ICONS[severity]!!
RuleType.VULNERABILITY -> VULNERABILITY_ICONS[severity]!!
RuleType.SECURITY_HOTSPOT -> throw UnsupportedOperationException("Security Hotspots do not support severity")
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ object SonarLintIntelliJClient : SonarLintRpcClientDelegate {
}
val connection = connectionOpt.get()
return if (connection.token != null) {
Either.forLeft(TokenDto(connection.token))
Either.forLeft(TokenDto(connection.token!!))
} else {
Either.forRight(UsernamePasswordDto(connection.login, connection.password))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class ReopenIssueAction(private var issue: LiveIssue? = null) : AbstractSonarAct

var serverKey: String? = null
if (issue is LiveIssue) {
serverKey = issue.getServerKey() ?: issue.id.toString()
serverKey = issue.getServerKey() ?: issue.getId().toString()
} else if (issue is LocalTaintVulnerability) {
serverKey = issue.key()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBLoadingPanel;
import com.intellij.ui.components.JBPanel;
import com.intellij.ui.components.JBPanelWithEmptyText;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.components.JBTextArea;
import com.intellij.ui.components.fields.ExpandableTextField;
Expand Down Expand Up @@ -139,6 +140,7 @@ public class RuleConfigurationPanel implements Disposable, ConfigurationPanel<So
private RulesParamsSeparator rulesParamsSeparator;
private String selectedRuleKey;
private RuleHeaderPanel ruleHeaderPanel;
private JBPanelWithEmptyText rulePanel;

public RuleConfigurationPanel() {
createUIComponents();
Expand Down Expand Up @@ -357,8 +359,9 @@ private ActionToolbar createTreeToolbarPanel() {
return actionToolbar;
}

private JPanel createUIComponents() {
var rulePanel = new JBPanel<>(new BorderLayout());
private void createUIComponents() {
rulePanel = new JBPanelWithEmptyText(new BorderLayout());
rulePanel.withEmptyText(EMPTY_HTML);
rulePanel.setBorder(JBUI.Borders.emptyLeft(5));

ruleHeaderPanel = new RuleHeaderPanel(this);
Expand Down Expand Up @@ -429,17 +432,27 @@ protected void hyperlinkActivated(HyperlinkEvent e) {
labelPanel.add(configureRuleLabel);
labelPanel.add(ruleServerLabel);
panel.add(labelPanel, BorderLayout.NORTH);
return panel;
}

private void initOptionsAndDescriptionPanel() {
myParamsPanel.removeAll();
ruleDescription.removeAll();
ruleHeaderPanel.showMessage(EMPTY_HTML);
setEmptyDisplay(EMPTY_HTML);
myParamsPanel.validate();
myParamsPanel.repaint();
}

private void setEmptyDisplay(String msg) {
rulePanel.withEmptyText(msg);
ruleHeaderPanel.setVisible(false);
ruleDescription.setVisible(false);
}

private void unsetEmptyDisplay() {
ruleHeaderPanel.setVisible(true);
ruleDescription.setVisible(true);
}

private JScrollPane initTreeScrollPane() {
// create tree table
model = new RulesTreeTableModel(new RulesTreeNode.Root());
Expand Down Expand Up @@ -494,9 +507,8 @@ private void updateParamsAndDescriptionPanel() {
if (singleNode != null) {
updateParamsAndDescriptionPanel(singleNode);
} else {
ruleHeaderPanel.showMessage("Multiple rules are selected.");
setEmptyDisplay("Multiple rules are selected.");
myParamsPanel.removeAll();

}
} else {
initOptionsAndDescriptionPanel();
Expand All @@ -507,8 +519,8 @@ private void updateParamsAndDescriptionPanel() {
}

private void updateParamsAndDescriptionPanel(RulesTreeNode.Rule singleNode) {
ruleHeaderPanel.updateForRuleConfiguration(singleNode.getKey(), singleNode.type(), singleNode.severity(), singleNode.attribute(),
singleNode.impacts());
ruleHeaderPanel.updateForRuleConfiguration(singleNode.attribute(), singleNode.impacts(), singleNode.getKey());
unsetEmptyDisplay();
var fileType = RuleLanguages.Companion.findFileTypeByRuleLanguage(singleNode.language());

runOnPooledThread(project, () ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@
import org.sonarsource.sonarlint.core.client.utils.ImpactSeverity;
import org.sonarsource.sonarlint.core.rpc.protocol.backend.rules.ImpactDto;
import org.sonarsource.sonarlint.core.rpc.protocol.backend.rules.RuleDefinitionDto;
import org.sonarsource.sonarlint.core.rpc.protocol.common.IssueSeverity;
import org.sonarsource.sonarlint.core.rpc.protocol.common.Language;
import org.sonarsource.sonarlint.core.rpc.protocol.common.RuleType;
import org.sonarsource.sonarlint.core.rpc.protocol.common.SoftwareQuality;

public abstract class RulesTreeNode<T> extends DefaultMutableTreeNode {
Expand Down Expand Up @@ -114,7 +112,7 @@ public Rule(RuleDefinitionDto details, boolean activated, Map<String, String> no
this.details = details;
this.activated = activated;
this.nonDefaultParams = new HashMap<>(nonDefaultParams);
var highestQualityImpact = details.getDefaultImpacts().stream().max(Comparator.comparing(ImpactDto::getImpactSeverity));
var highestQualityImpact = details.getSoftwareImpacts().stream().max(Comparator.comparing(ImpactDto::getImpactSeverity));
this.highestQuality = highestQualityImpact.map(ImpactDto::getSoftwareQuality).orElse(null);
this.highestImpact = highestQualityImpact.map(ImpactDto::getImpactSeverity).map(ImpactSeverity::fromDto).orElse(null);
}
Expand All @@ -137,15 +135,7 @@ public CleanCodeAttribute attribute() {
}

public List<ImpactDto> impacts() {
return details.getDefaultImpacts();
}

public IssueSeverity severity() {
return details.getSeverity();
}

public RuleType type() {
return details.getType();
return details.getSoftwareImpacts();
}

public Language language() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ class ModuleBindingPanel(private val project: Project, currentConnectionSupplier
projectKeyTextField.emptyText.text = "Input project key or search one"
val projectKeyLabel = JLabel("Project key:")
projectKeyLabel.labelFor = projectKeyTextField
val insets = JBUI.insets(2, 0, 0, 0)
val insets = JBUI.insetsTop(2)
moduleBindingDetailsPanel.add(
projectKeyLabel, GridBagConstraints(
0, 0, 1, 1, 0.0, 0.0,
Expand Down
Loading

0 comments on commit 9aa4dbd

Please sign in to comment.