Skip to content

Commit a5d7ece

Browse files
authored
CM-48118 - Add detection sorting by line number in addition to severity (#87)
1 parent 1bec428 commit a5d7ece

File tree

17 files changed

+55
-25
lines changed

17 files changed

+55
-25
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
## [Unreleased]
66

7+
## [2.6.0] - 2025-05-12
8+
9+
- Add detection sorting by line number in addition to severity
10+
711
## [2.5.0] - 2025-02-24
812

913
- Add proper support for disabled modules
@@ -147,6 +151,8 @@
147151

148152
The first public release of the plugin.
149153

154+
[2.6.0]: https://github.com/cycodehq/intellij-platform-plugin/releases/tag/v2.6.0
155+
150156
[2.5.0]: https://github.com/cycodehq/intellij-platform-plugin/releases/tag/v2.5.0
151157

152158
[2.4.1]: https://github.com/cycodehq/intellij-platform-plugin/releases/tag/v2.4.1
@@ -207,4 +213,4 @@ The first public release of the plugin.
207213

208214
[1.0.0]: https://github.com/cycodehq/intellij-platform-plugin/releases/tag/v1.0.0
209215

210-
[Unreleased]: https://github.com/cycodehq/intellij-platform-plugin/compare/v2.5.0...HEAD
216+
[Unreleased]: https://github.com/cycodehq/intellij-platform-plugin/compare/v2.6.0...HEAD

CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
* @MarshalX @MichalBor @MaorDavidzon @artem-fedorov @elsapet @gotbadger @cfabianski
1+
* @MarshalX @elsapet @gotbadger @cfabianski

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ pluginGroup = com.cycode.plugin
44
pluginName = Cycode
55
pluginRepositoryUrl = https://github.com/cycodehq/intellij-platform-plugin
66
# SemVer format -> https://semver.org
7-
pluginVersion = 2.5.0
7+
pluginVersion = 2.6.0
88

99
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
1010
pluginSinceBuild = 231
11-
pluginUntilBuild = 251.*
11+
pluginUntilBuild = 252.*
1212

1313
# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
1414
platformType = IC

src/main/kotlin/com/cycode/plugin/annotators/annotationAppliers/IacApplier.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class IacApplier(private val scanResults: ScanResultsService) : AnnotationApplie
3434
val severity = convertSeverity(detection.severity)
3535

3636
// IaC doesn't provide start and end positions, so we have to calculate them from the line number
37-
val line = detection.detectionDetails.lineInFile - 1
37+
val line = detection.detectionDetails.getLineNumber() - 1
3838
val startOffset = psiFile.text.lines().take(line).sumOf { it.length + 1 }
3939
val endOffset = startOffset + psiFile.text.lines()[line].length
4040

src/main/kotlin/com/cycode/plugin/annotators/annotationAppliers/SastApplier.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class SastApplier(private val scanResults: ScanResultsService) : AnnotationAppli
3333
val severity = convertSeverity(detection.severity)
3434

3535
// SAST doesn't provide start and end positions, so we have to calculate them from the line number
36-
val line = detection.detectionDetails.lineInFile - 1
36+
val line = detection.detectionDetails.getLineNumber() - 1
3737
val startOffset = psiFile.text.lines().take(line).sumOf { it.length + 1 }
3838
val endOffset = startOffset + psiFile.text.lines()[line].length
3939

src/main/kotlin/com/cycode/plugin/annotators/annotationAppliers/ScaApplier.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class ScaApplier(private val scanResults: ScanResultsService) : AnnotationApplie
4444
val severity = convertSeverity(detection.severity)
4545

4646
// SCA doesn't provide start and end positions, so we have to calculate them from the line number
47-
val line = detection.detectionDetails.lineInFile - 1
47+
val line = detection.detectionDetails.getLineNumber() - 1
4848
val startOffset = psiFile.text.lines().take(line).sumOf { it.length + 1 }
4949
val endOffset = startOffset + psiFile.text.lines()[line].length
5050

src/main/kotlin/com/cycode/plugin/cli/models/scanResult/ScanDetectionDetailsBase.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,9 @@ package com.cycode.plugin.cli.models.scanResult
22

33
interface ScanDetectionDetailsBase {
44
fun getFilepath(): String
5+
/**
6+
* Gets the line number.
7+
* @return The 1-based line number (first line is 1, not 0)
8+
*/
9+
fun getLineNumber(): Int
510
}

src/main/kotlin/com/cycode/plugin/cli/models/scanResult/iac/IacDetection.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ data class IacDetection(
2121
}
2222

2323
override fun getFormattedNodeTitle(): String {
24-
return CycodeBundle.message("iacNodeTitle", detectionDetails.lineInFile, getFormattedMessage())
24+
return CycodeBundle.message("iacNodeTitle", detectionDetails.getLineNumber(), getFormattedMessage())
2525
}
2626
}

src/main/kotlin/com/cycode/plugin/cli/models/scanResult/iac/IacDetectionDetails.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,8 @@ data class IacDetectionDetails(
1919
override fun getFilepath(): String {
2020
return fileName
2121
}
22+
23+
override fun getLineNumber(): Int {
24+
return lineInFile
25+
}
2226
}

src/main/kotlin/com/cycode/plugin/cli/models/scanResult/sast/SastDetection.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ data class SastDetection(
2121
}
2222

2323
override fun getFormattedNodeTitle(): String {
24-
return CycodeBundle.message("sastNodeTitle", detectionDetails.lineInFile, getFormattedMessage())
24+
return CycodeBundle.message("sastNodeTitle", detectionDetails.getLineNumber(), getFormattedMessage())
2525
}
2626
}

src/main/kotlin/com/cycode/plugin/cli/models/scanResult/sast/SastDetectionDetails.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,8 @@ data class SastDetectionDetails(
2121
override fun getFilepath(): String {
2222
return if (filePath.startsWith("/")) filePath else "/$filePath"
2323
}
24+
25+
override fun getLineNumber(): Int {
26+
return lineInFile
27+
}
2428
}

src/main/kotlin/com/cycode/plugin/cli/models/scanResult/sca/ScaDetection.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ data class ScaDetection(
2929
override fun getFormattedNodeTitle(): String {
3030
return CycodeBundle.message(
3131
"scaNodeTitle",
32-
detectionDetails.lineInFile,
32+
detectionDetails.getLineNumber(),
3333
getFormattedTitle(),
3434
)
3535
}

src/main/kotlin/com/cycode/plugin/cli/models/scanResult/sca/ScaDetectionDetails.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,8 @@ data class ScaDetectionDetails(
2323
override fun getFilepath(): String {
2424
return fileName
2525
}
26+
27+
override fun getLineNumber(): Int {
28+
return lineInFile
29+
}
2630
}

src/main/kotlin/com/cycode/plugin/cli/models/scanResult/secret/SecretDetection.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package com.cycode.plugin.cli.models.scanResult.secret
33
import com.cycode.plugin.CycodeBundle
44
import com.cycode.plugin.cli.models.scanResult.DetectionBase
55

6-
const val IDE_ENTRY_LINE_NUMBER = 1
7-
86
data class SecretDetection(
97
override val id: String,
108
override val severity: String,
@@ -23,6 +21,6 @@ data class SecretDetection(
2321
}
2422

2523
override fun getFormattedNodeTitle(): String {
26-
return CycodeBundle.message("secretsNodeTitle", detectionDetails.line + IDE_ENTRY_LINE_NUMBER, type)
24+
return CycodeBundle.message("secretsNodeTitle", detectionDetails.getLineNumber(), type)
2725
}
2826
}

src/main/kotlin/com/cycode/plugin/cli/models/scanResult/secret/SecretDetectionDetails.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package com.cycode.plugin.cli.models.scanResult.secret
22

33
import com.cycode.plugin.cli.models.scanResult.ScanDetectionDetailsBase
44

5+
const val IDE_ENTRY_LINE_NUMBER = 1
6+
57
data class SecretDetectionDetails(
68
val sha512: String,
79
val provider: String,
@@ -22,4 +24,8 @@ data class SecretDetectionDetails(
2224
override fun getFilepath(): String {
2325
return "$filePath$fileName"
2426
}
27+
28+
override fun getLineNumber(): Int {
29+
return line + IDE_ENTRY_LINE_NUMBER
30+
}
2531
}

src/main/kotlin/com/cycode/plugin/components/toolWindow/components/treeView/TreeView.kt

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,11 @@ class TreeView(
154154
createNodeCallback: (detection: DetectionBase) -> DefaultMutableTreeNode
155155
) {
156156
val filteredDetections = scanResults.detections.filter {
157-
severityFilter?.getOrDefault(it.severity.lowercase(), true) ?: true
157+
severityFilter?.getOrDefault(it.severity.lowercase(), true) != false
158158
}
159-
val sortedDetections = filteredDetections.sortedByDescending { getSeverityWeight(it.severity) }
160-
val detectionsByFile = sortedDetections.groupBy { it.detectionDetails.getFilepath() }
159+
val detectionsByFile = filteredDetections.groupBy { it.detectionDetails.getFilepath() }
161160

162-
rootNodes.setNodeSummary(scanType, getDetectionSummary(sortedDetections))
161+
rootNodes.setNodeSummary(scanType, getDetectionSummary(filteredDetections))
163162

164163
val projectRoot = project.basePath?.let { File(it) } ?: File("")
165164

@@ -173,7 +172,13 @@ class TreeView(
173172
AllIcons.Actions.Annotate
174173

175174
val fileNode = createNode(FileNode(projectRelativePath, summary, icon))
176-
for (detection in detections) {
175+
176+
val sortedDetections = detections.sortedWith(
177+
compareByDescending<DetectionBase> { getSeverityWeight(it.severity) }
178+
.thenBy { it.detectionDetails.getLineNumber() }
179+
)
180+
181+
for (detection in sortedDetections) {
177182
fileNode.add(createNodeCallback(detection))
178183
}
179184

src/main/kotlin/com/cycode/plugin/components/toolWindow/components/treeView/utils.kt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ import com.intellij.psi.PsiFile
1010
import com.intellij.psi.PsiManager
1111
import java.io.File
1212

13-
const val DIFFERENCE_BETWEEN_SCA_LINE_NUMBERS = 1
14-
const val DIFFERENCE_BETWEEN_IAC_LINE_NUMBERS = 1
15-
const val DIFFERENCE_BETWEEN_SAST_LINE_NUMBERS = 1
13+
const val DIFFERENCE_BETWEEN_CYCODE_AND_IDE_LINE_NUMBER = 1
1614

1715
fun getPsiFile(project: Project, filePath: String): PsiFile? {
1816
val virtualFile = VirtualFileManager.getInstance().findFileByUrl("file://$filePath") ?: return null
@@ -31,25 +29,25 @@ private fun openFileInEditor(project: Project, filePath: String, lineNumber: Int
3129

3230
private fun openSecretDetectionInFile(project: Project, node: SecretDetectionNode) {
3331
val filePath = node.detection.detectionDetails.getFilepath()
34-
val line = node.detection.detectionDetails.line
32+
val line = node.detection.detectionDetails.getLineNumber() - DIFFERENCE_BETWEEN_CYCODE_AND_IDE_LINE_NUMBER
3533
openFileInEditor(project, filePath, line)
3634
}
3735

3836
private fun openScaDetectionInFile(project: Project, node: ScaDetectionNode) {
3937
val filePath = node.detection.detectionDetails.getFilepath()
40-
val line = node.detection.detectionDetails.lineInFile - DIFFERENCE_BETWEEN_SCA_LINE_NUMBERS
38+
val line = node.detection.detectionDetails.getLineNumber() - DIFFERENCE_BETWEEN_CYCODE_AND_IDE_LINE_NUMBER
4139
openFileInEditor(project, filePath, line)
4240
}
4341

4442
private fun openIacDetectionInFile(project: Project, node: IacDetectionNode) {
4543
val filePath = node.detection.detectionDetails.getFilepath()
46-
val line = node.detection.detectionDetails.lineInFile - DIFFERENCE_BETWEEN_IAC_LINE_NUMBERS
44+
val line = node.detection.detectionDetails.getLineNumber() - DIFFERENCE_BETWEEN_CYCODE_AND_IDE_LINE_NUMBER
4745
openFileInEditor(project, filePath, line)
4846
}
4947

5048
private fun openSastDetectionInFile(project: Project, node: SastDetectionNode) {
5149
val filePath = node.detection.detectionDetails.getFilepath()
52-
val line = node.detection.detectionDetails.lineInFile - DIFFERENCE_BETWEEN_SAST_LINE_NUMBERS
50+
val line = node.detection.detectionDetails.getLineNumber() - DIFFERENCE_BETWEEN_CYCODE_AND_IDE_LINE_NUMBER
5351
openFileInEditor(project, filePath, line)
5452
}
5553

0 commit comments

Comments
 (0)