diff --git a/CHANGELOG.md b/CHANGELOG.md index 7efe8d8..9910ea7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ## [Unreleased] +## [1.10.0] - 2025-05-14 + +- Add detection sorting by line number in addition to severity + ## [1.9.0] - 2025-02-24 - Add tree view filtering by severity @@ -85,6 +89,8 @@ The first public release of the extension. +[1.10.0]: https://github.com/cycodehq/visual-studio-extension/releases/tag/v1.10.0 + [1.9.0]: https://github.com/cycodehq/visual-studio-extension/releases/tag/v1.9.0 [1.8.0]: https://github.com/cycodehq/visual-studio-extension/releases/tag/v1.8.0 @@ -119,4 +125,4 @@ The first public release of the extension. [1.0.0]: https://github.com/cycodehq/visual-studio-extension/releases/tag/v1.0.0 -[Unreleased]: https://github.com/cycodehq/visual-studio-extension/compare/v1.9.0...HEAD +[Unreleased]: https://github.com/cycodehq/visual-studio-extension/compare/v1.10.0...HEAD diff --git a/global.json b/global.json index 9cdb723..f77a0a3 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.404", - "rollForward": "latestFeature" + "version": "8.0.408", + "rollForward": "disable" } } \ No newline at end of file diff --git a/src/extension/Cycode.VisualStudio.Extension.14.0-16.0/source.extension.vsixmanifest b/src/extension/Cycode.VisualStudio.Extension.14.0-16.0/source.extension.vsixmanifest index 175ebd6..af8d843 100644 --- a/src/extension/Cycode.VisualStudio.Extension.14.0-16.0/source.extension.vsixmanifest +++ b/src/extension/Cycode.VisualStudio.Extension.14.0-16.0/source.extension.vsixmanifest @@ -1,7 +1,7 @@ - + Cycode Cycode for Visual Studio IDE https://github.com/cycodehq/visual-studio-extension diff --git a/src/extension/Cycode.VisualStudio.Extension.17.0/source.extension.vsixmanifest b/src/extension/Cycode.VisualStudio.Extension.17.0/source.extension.vsixmanifest index ebd71cd..767502c 100644 --- a/src/extension/Cycode.VisualStudio.Extension.17.0/source.extension.vsixmanifest +++ b/src/extension/Cycode.VisualStudio.Extension.17.0/source.extension.vsixmanifest @@ -1,7 +1,7 @@ - + Cycode Cycode for Visual Studio IDE https://github.com/cycodehq/visual-studio-extension diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/DetectionDetailsBase.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/DetectionDetailsBase.cs index 813c576..93a222b 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/DetectionDetailsBase.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/DetectionDetailsBase.cs @@ -2,4 +2,6 @@ public abstract class DetectionDetailsBase { public abstract string GetFilePath(); + // This method returns a 1-indexed line number + public abstract int GetLineNumber(); } \ No newline at end of file diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Iac/IacDetection.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Iac/IacDetection.cs index ce69dff..783b808 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Iac/IacDetection.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Iac/IacDetection.cs @@ -31,6 +31,6 @@ public override string GetFormattedTitle() { } public override string GetFormattedNodeTitle() { - return $"line {DetectionDetails.LineInFile + 1}: {GetFormattedMessage()}"; + return $"line {DetectionDetails.GetLineNumber()}: {GetFormattedMessage()}"; } } \ No newline at end of file diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Iac/IacDetectionDetails.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Iac/IacDetectionDetails.cs index 479ae79..b749ad8 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Iac/IacDetectionDetails.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Iac/IacDetectionDetails.cs @@ -35,4 +35,8 @@ public class IacDetectionDetails : DetectionDetailsBase { public override string GetFilePath() { return FileName; } + + public override int GetLineNumber() { + return LineInFile; + } } \ No newline at end of file diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sast/SastDetection.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sast/SastDetection.cs index c52ef71..e78e572 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sast/SastDetection.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sast/SastDetection.cs @@ -31,6 +31,6 @@ public override string GetFormattedTitle() { } public override string GetFormattedNodeTitle() { - return $"line {DetectionDetails.LineInFile}: {GetFormattedMessage()}"; + return $"line {DetectionDetails.GetLineNumber()}: {GetFormattedMessage()}"; } } \ No newline at end of file diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sast/SastDetectionDetails.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sast/SastDetectionDetails.cs index 0b00773..4c8b4df 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sast/SastDetectionDetails.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sast/SastDetectionDetails.cs @@ -46,4 +46,8 @@ public class SastDetectionDetails : DetectionDetailsBase { public override string GetFilePath() { return FilePath; } + + public override int GetLineNumber() { + return LineInFile; + } } \ No newline at end of file diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sca/ScaDetection.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sca/ScaDetection.cs index 73cd373..446aba4 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sca/ScaDetection.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sca/ScaDetection.cs @@ -32,6 +32,6 @@ public override string GetFormattedTitle() { } public override string GetFormattedNodeTitle() { - return $"line {DetectionDetails.LineInFile}: {GetFormattedTitle()}"; + return $"line {DetectionDetails.GetLineNumber()}: {GetFormattedTitle()}"; } } \ No newline at end of file diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sca/ScaDetectionDetails.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sca/ScaDetectionDetails.cs index beae885..bac67d7 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sca/ScaDetectionDetails.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Sca/ScaDetectionDetails.cs @@ -37,4 +37,8 @@ public class ScaDetectionDetails : DetectionDetailsBase { public override string GetFilePath() { return FileName; } + + public override int GetLineNumber() { + return LineInFile; + } } \ No newline at end of file diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Secret/SecretDetection.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Secret/SecretDetection.cs index 21dae55..11c0830 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Secret/SecretDetection.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Secret/SecretDetection.cs @@ -31,6 +31,6 @@ public override string GetFormattedTitle() { } public override string GetFormattedNodeTitle() { - return $"line {DetectionDetails.Line + 1}: a hardcoded {Type} is used"; + return $"line {DetectionDetails.GetLineNumber()}: a hardcoded {Type} is used"; } } \ No newline at end of file diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Secret/SecretDetectionDetails.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Secret/SecretDetectionDetails.cs index 5d37066..7fb0d7c 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Secret/SecretDetectionDetails.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Cli/DTO/ScanResult/Secret/SecretDetectionDetails.cs @@ -40,4 +40,8 @@ public class SecretDetectionDetails : DetectionDetailsBase { public override string GetFilePath() { return $"{FilePath}{FileName}"; } + + public override int GetLineNumber() { + return Line + 1; // 1-indexed + } } \ No newline at end of file diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Components/TreeView/CycodeTreeViewControl.xaml.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Components/TreeView/CycodeTreeViewControl.xaml.cs index 5304b0f..a4e09c4 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Components/TreeView/CycodeTreeViewControl.xaml.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Components/TreeView/CycodeTreeViewControl.xaml.cs @@ -44,7 +44,7 @@ private void OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs case SecretDetectionNode secretDetectionNode: { SecretDetection detection = secretDetectionNode.Detection; filePath = detection.DetectionDetails.GetFilePath(); - line = detection.DetectionDetails.Line + 1; + line = detection.DetectionDetails.GetLineNumber(); _toolWindowMessengerService.Send( new MessageEventArgs(MessengerCommand.LoadSecretViolationCardControl, detection) ); @@ -53,7 +53,7 @@ private void OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs case ScaDetectionNode scaDetectionNode: { ScaDetection detection = scaDetectionNode.Detection; filePath = detection.DetectionDetails.GetFilePath(); - line = detection.DetectionDetails.LineInFile; + line = detection.DetectionDetails.GetLineNumber(); _toolWindowMessengerService.Send( new MessageEventArgs(MessengerCommand.LoadScaViolationCardControl, detection) ); @@ -62,7 +62,7 @@ private void OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs case IacDetectionNode iacDetectionNode: { IacDetection detection = iacDetectionNode.Detection; filePath = detection.DetectionDetails.GetFilePath(); - line = detection.DetectionDetails.LineInFile + 1; + line = detection.DetectionDetails.GetLineNumber(); _toolWindowMessengerService.Send( new MessageEventArgs(MessengerCommand.LoadIacViolationCardControl, detection) ); @@ -71,7 +71,7 @@ private void OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs case SastDetectionNode sastDetectionNode: { SastDetection detection = sastDetectionNode.Detection; filePath = detection.DetectionDetails.GetFilePath(); - line = detection.DetectionDetails.LineInFile; + line = detection.DetectionDetails.GetLineNumber(); _toolWindowMessengerService.Send( new MessageEventArgs(MessengerCommand.LoadSastViolationCardControl, detection) ); @@ -144,14 +144,11 @@ Func createNodeCallback List severityFilteredDetections = detections .Where(detection => !enabledSeverityFilters.Contains(detection.Severity.ToLower())) .ToList(); - List sortedDetections = severityFilteredDetections - .OrderByDescending(detection => GetSeverityWeight(detection.Severity)) - .ToList(); IEnumerable> detectionsByFile = - sortedDetections.GroupBy(detection => detection.GetDetectionDetails().GetFilePath()); + severityFilteredDetections.GroupBy(detection => detection.GetDetectionDetails().GetFilePath()); ScanTypeNode scanTypeNode = RootNodesManager.GetScanTypeNode(scanType); - scanTypeNode.Summary = GetRootNodeSummary(sortedDetections); + scanTypeNode.Summary = GetRootNodeSummary(severityFilteredDetections); foreach (IGrouping detectionsInFile in detectionsByFile) { string filePath = detectionsInFile.Key; @@ -162,7 +159,12 @@ Func createNodeCallback Icon = ExtensionIcons.GetFileIconPath(filePath) }; - foreach (DetectionBase detection in detectionsInFile) fileNode.Items.Add(createNodeCallback(detection)); + List sortedDetectionsInFile = detectionsInFile + .OrderByDescending(detection => GetSeverityWeight(detection.Severity)) + .ThenBy(detection => detection.GetDetectionDetails().GetLineNumber()) + .ToList(); + + foreach (DetectionBase detection in sortedDetectionsInFile) fileNode.Items.Add(createNodeCallback(detection)); scanTypeNode.Items.Add(fileNode); } diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/IacErrorTaskCreator.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/IacErrorTaskCreator.cs index befe608..8bf9021 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/IacErrorTaskCreator.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/IacErrorTaskCreator.cs @@ -10,7 +10,7 @@ public static List CreateErrorTasks(List detections) { errorTasks.AddRange(detections.Select(detection => new ErrorTask { Text = $"Cycode: {detection.GetFormattedTitle()}", - Line = detection.DetectionDetails.LineInFile, + Line = detection.DetectionDetails.GetLineNumber() - 1, Document = detection.DetectionDetails.GetFilePath(), Category = TaskCategory.User, ErrorCategory = ErrorCategoryUtilities.GetTaskErrorCategory(detection.Severity), diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/SastErrorTaskCreator.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/SastErrorTaskCreator.cs index 285d2ba..c0ee446 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/SastErrorTaskCreator.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/SastErrorTaskCreator.cs @@ -10,7 +10,7 @@ public static List CreateErrorTasks(List detections) { errorTasks.AddRange(detections.Select(detection => new ErrorTask { Text = $"Cycode: {detection.GetFormattedTitle()}", - Line = detection.DetectionDetails.LineInFile - 1, + Line = detection.DetectionDetails.GetLineNumber() - 1, Document = detection.DetectionDetails.GetFilePath(), Category = TaskCategory.User, ErrorCategory = ErrorCategoryUtilities.GetTaskErrorCategory(detection.Severity), diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/ScaErrorTaskCreator.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/ScaErrorTaskCreator.cs index 5b9388a..fb4ef3a 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/ScaErrorTaskCreator.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/ScaErrorTaskCreator.cs @@ -10,7 +10,7 @@ public static List CreateErrorTasks(List detections) { errorTasks.AddRange(detections.Select(detection => new ErrorTask { Text = $"Cycode: {detection.GetFormattedTitle()}", - Line = detection.DetectionDetails.LineInFile - 1, + Line = detection.DetectionDetails.GetLineNumber() - 1, Document = detection.DetectionDetails.GetFilePath(), Category = TaskCategory.User, ErrorCategory = ErrorCategoryUtilities.GetTaskErrorCategory(detection.Severity), diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/SecretsErrorTaskCreator.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/SecretsErrorTaskCreator.cs index 9b625fb..bef0281 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/SecretsErrorTaskCreator.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorList/TaskCreators/SecretsErrorTaskCreator.cs @@ -10,7 +10,7 @@ public static List CreateErrorTasks(List detections) errorTasks.AddRange(detections.Select(detection => new ErrorTask { Text = $"Cycode: {detection.GetFormattedTitle()}", - Line = detection.DetectionDetails.Line, + Line = detection.DetectionDetails.GetLineNumber() - 1, Document = detection.DetectionDetails.GetFilePath(), Category = TaskCategory.User, ErrorCategory = ErrorCategoryUtilities.GetTaskErrorCategory(detection.Severity), diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/IacTagSpansCreator.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/IacTagSpansCreator.cs index ffba8b7..9f042ed 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/IacTagSpansCreator.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/IacTagSpansCreator.cs @@ -23,7 +23,7 @@ public static List> CreateTagSpans(ITextSnapshot snapshot .ToList(); tagSpans.AddRange(from detection in detections - let line = detection.DetectionDetails.LineInFile + let line = detection.DetectionDetails.GetLineNumber() - 1 let startSnapshotPoint = snapshot.GetLineFromLineNumber(line).Start let endSnapshotPoint = snapshot.GetLineFromLineNumber(line).End let snapshotSpan = new SnapshotSpan(startSnapshotPoint, endSnapshotPoint) diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/SastTagSpansCreator.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/SastTagSpansCreator.cs index 46d25b3..4e61760 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/SastTagSpansCreator.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/SastTagSpansCreator.cs @@ -23,7 +23,7 @@ public static List> CreateTagSpans(ITextSnapshot snapshot .ToList(); tagSpans.AddRange(from detection in detections - let line = detection.DetectionDetails.LineInFile - 1 + let line = detection.DetectionDetails.GetLineNumber() - 1 let startSnapshotPoint = snapshot.GetLineFromLineNumber(line).Start let endSnapshotPoint = snapshot.GetLineFromLineNumber(line).End let snapshotSpan = new SnapshotSpan(startSnapshotPoint, endSnapshotPoint) diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/ScaTagSpansCreator.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/ScaTagSpansCreator.cs index dfb9399..e7c4e44 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/ScaTagSpansCreator.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/ScaTagSpansCreator.cs @@ -23,7 +23,7 @@ public static List> CreateTagSpans(ITextSnapshot snapshot .ToList(); tagSpans.AddRange(from detection in detections - let line = detection.DetectionDetails.LineInFile - 1 + let line = detection.DetectionDetails.GetLineNumber() - 1 let length = snapshot.GetLineFromLineNumber(line).Length let startSnapshotPoint = snapshot.GetLineFromLineNumber(line).Start.Add(0) let endSnapshotPoint = snapshot.GetLineFromLineNumber(line).Start.Add(length) diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/SecretsTagSpansCreator.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/SecretsTagSpansCreator.cs index 966c37c..ee87456 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/SecretsTagSpansCreator.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/Services/ErrorTagger/TagSpansCreators/SecretsTagSpansCreator.cs @@ -23,7 +23,7 @@ public static List> CreateTagSpans(ITextSnapshot snapshot .ToList(); tagSpans.AddRange(from detection in detections - let line = detection.DetectionDetails.Line + let line = detection.DetectionDetails.GetLineNumber() - 1 let column = ErrorTaggerUtilities.CalculateColumn(snapshot, detection.DetectionDetails.StartPosition) let length = detection.DetectionDetails.Length let startSnapshotPoint = snapshot.GetLineFromLineNumber(line).Start.Add(column) diff --git a/src/extension/Cycode.VisualStudio.Extension.Shared/source.extension.cs b/src/extension/Cycode.VisualStudio.Extension.Shared/source.extension.cs index a8d6549..4cf3f4b 100644 --- a/src/extension/Cycode.VisualStudio.Extension.Shared/source.extension.cs +++ b/src/extension/Cycode.VisualStudio.Extension.Shared/source.extension.cs @@ -3,5 +3,5 @@ namespace Cycode.VisualStudio.Extension.Shared; internal sealed class Vsix { public const string Name = "Cycode"; public const string Description = "Cycode for Visual Studio IDE"; - public const string Version = "1.9.0"; + public const string Version = "1.10.0"; } \ No newline at end of file