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