1
+ module internal Sarif
2
+
3
+ open FSharpLint.Framework
4
+ open System.IO
5
+ open System
6
+ open Microsoft.CodeAnalysis .Sarif
7
+ open Microsoft.CodeAnalysis .Sarif .Writers
8
+ open FSharpLint.Console .Output
9
+
10
+ let writeReport ( results : Suggestion.LintWarning list ) ( codeRoot : string option ) ( report : string ) ( logger : IOutput ) =
11
+ try
12
+ let codeRoot =
13
+ match codeRoot with
14
+ | None -> Directory.GetCurrentDirectory() |> Uri
15
+ | Some root -> Path.GetFullPath root |> Uri
16
+
17
+ // Construct full path to ensure path separators are normalized.
18
+ let report = Path.GetFullPath report
19
+ // Ensure the parent directory exists
20
+ let reportFile = FileInfo( report)
21
+ reportFile.Directory.Create()
22
+
23
+ let driver = ToolComponent()
24
+ driver.Name <- " FSharpLint.Console"
25
+ driver.InformationUri <- Uri( " https://fsprojects.github.io/FSharpLint/" )
26
+ driver.Version <- string< Version> ( System.Reflection.Assembly.GetExecutingAssembly() .GetName() .Version)
27
+ let tool = Tool()
28
+ tool.Driver <- driver
29
+ let run = Run()
30
+ run.Tool <- tool
31
+
32
+ use sarifLogger =
33
+ new SarifLogger(
34
+ report,
35
+ logFilePersistenceOptions =
36
+ ( FilePersistenceOptions.PrettyPrint ||| FilePersistenceOptions.ForceOverwrite),
37
+ run = run,
38
+ levels = BaseLogger.ErrorWarningNote,
39
+ kinds = BaseLogger.Fail,
40
+ closeWriterOnDispose = true
41
+ )
42
+
43
+ sarifLogger.AnalysisStarted()
44
+
45
+ for analyzerResult in results do
46
+ let reportDescriptor = ReportingDescriptor()
47
+ reportDescriptor.Id <- analyzerResult.RuleIdentifier
48
+ reportDescriptor.Name <- analyzerResult.RuleName
49
+
50
+ (*
51
+ analyzerResult.ShortDescription
52
+ |> Option.iter (fun shortDescription ->
53
+ reportDescriptor.ShortDescription <-
54
+ MultiformatMessageString(shortDescription, shortDescription, dict [])
55
+ )
56
+ *)
57
+
58
+ let helpUri = $" https://fsprojects.github.io/FSharpLint/how-tos/rules/%s {analyzerResult.RuleIdentifier}.html"
59
+ reportDescriptor.HelpUri <- Uri( helpUri)
60
+
61
+ let result = Result()
62
+ result.RuleId <- reportDescriptor.Id
63
+
64
+ (*
65
+ result.Level <-
66
+ match analyzerResult.Message.Severity with
67
+ | Severity.Info -> FailureLevel.Note
68
+ | Severity.Hint -> FailureLevel.Note
69
+ | Severity.Warning -> FailureLevel.Warning
70
+ | Severity.Error -> FailureLevel.Error
71
+ *)
72
+ result.Level <- FailureLevel.Warning
73
+
74
+ let msg = Message()
75
+ msg.Text <- analyzerResult.Details.Message
76
+ result.Message <- msg
77
+
78
+ let physicalLocation = PhysicalLocation()
79
+
80
+ physicalLocation.ArtifactLocation <-
81
+ let al = ArtifactLocation()
82
+ al.Uri <- codeRoot.MakeRelativeUri( Uri( analyzerResult.Details.Range.FileName))
83
+ al
84
+
85
+ physicalLocation.Region <-
86
+ let r = Region()
87
+ r.StartLine <- analyzerResult.Details.Range.StartLine
88
+ r.StartColumn <- analyzerResult.Details.Range.StartColumn + 1
89
+ r.EndLine <- analyzerResult.Details.Range.EndLine
90
+ r.EndColumn <- analyzerResult.Details.Range.EndColumn + 1
91
+ r
92
+
93
+ let location : Location = Location()
94
+ location.PhysicalLocation <- physicalLocation
95
+ result.Locations <- [| location |]
96
+
97
+ sarifLogger.Log( reportDescriptor, result, System.Nullable())
98
+
99
+ sarifLogger.AnalysisStopped( RuntimeConditions.None)
100
+
101
+ sarifLogger.Dispose()
102
+ with ex ->
103
+ logger.WriteError( $" Could not write sarif to %s {report}: %s {ex.Message}" )
0 commit comments