Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept direct fsc arguments as input. #129

Merged
merged 2 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
## [0.17.0] - 2023-10-26

### Changed
* [Use fixed version of FCS and FSharp.Core](https://github.com/ionide/FSharp.Analyzers.SDK/pull/127) (thanks @nojaf!)
* [Allow to specify multiple analyzers-paths](https://github.com/ionide/FSharp.Analyzers.SDK/pull/128) (thanks @nojaf!)

### Added
* [Accept direct fsc arguments as input](https://github.com/ionide/FSharp.Analyzers.SDK/pull/129) (thanks @nojaf!)

## [0.16.0] - 2023-10-16

### Added
Expand Down
79 changes: 67 additions & 12 deletions src/FSharp.Analyzers.Cli/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type Arguments =
| Ignore_Files of string list
| Exclude_Analyzer of string list
| Report of string
| FSC_Args of string
| Verbose

interface IArgParserTemplate with
Expand All @@ -30,6 +31,7 @@ type Arguments =
| Exclude_Analyzer _ -> "The names of analyzers that should not be executed."
| Report _ -> "Write the result messages to a (sarif) report file."
| Verbose -> "Verbose logging."
| FSC_Args _ -> "Pass in the raw fsc compiler arguments. Cannot be combined with the `--project` flag."

let mutable verbose = false

Expand Down Expand Up @@ -71,16 +73,18 @@ let loadProject toolsPath projPath =
return fcsPo
}

let runProject (client: Client<CliAnalyzerAttribute, CliContext>) toolsPath proj (globs: Glob list) =
let runProjectAux
(client: Client<CliAnalyzerAttribute, CliContext>)
(fsharpOptions: FSharpProjectOptions)
(ignoreFiles: Glob list)
=
async {
let path = Path.Combine(Environment.CurrentDirectory, proj) |> Path.GetFullPath
let! option = loadProject toolsPath path
let! checkProjectResults = fcs.ParseAndCheckProject(option)
let! checkProjectResults = fcs.ParseAndCheckProject(fsharpOptions)

let! messagesPerAnalyzer =
option.SourceFiles
fsharpOptions.SourceFiles
|> Array.filter (fun file ->
match globs |> List.tryFind (fun g -> g.IsMatch file) with
match ignoreFiles |> List.tryFind (fun g -> g.IsMatch file) with
| Some g ->
printInfo $"Ignoring file %s{file} for pattern %s{g.Pattern}"
false
Expand All @@ -90,7 +94,7 @@ let runProject (client: Client<CliAnalyzerAttribute, CliContext>) toolsPath proj
let fileContent = File.ReadAllText fileName
let sourceText = SourceText.ofString fileContent

Utils.typeCheckFile fcs printError option fileName (Utils.SourceOfSource.SourceText sourceText)
Utils.typeCheckFile fcs printError fsharpOptions fileName (Utils.SourceOfSource.SourceText sourceText)
|> Option.map (Utils.createContext checkProjectResults fileName sourceText)
)
|> Array.map (fun ctx ->
Expand All @@ -107,6 +111,52 @@ let runProject (client: Client<CliAnalyzerAttribute, CliContext>) toolsPath proj
]
}

let runProject (client: Client<CliAnalyzerAttribute, CliContext>) toolsPath proj (globs: Glob list) =
async {
let path = Path.Combine(Environment.CurrentDirectory, proj) |> Path.GetFullPath
let! option = loadProject toolsPath path
return! runProjectAux client option globs
}

let fsharpFiles = set [| ".fs"; ".fsi"; ".fsx" |]

let isFSharpFile (file: string) =
Seq.exists (fun (ext: string) -> file.EndsWith ext) fsharpFiles

let runFscArgs (client: Client<CliAnalyzerAttribute, CliContext>) (fscArgs: string) (globs: Glob list) =
let fscArgs = fscArgs.Split(';', StringSplitOptions.RemoveEmptyEntries)

let sourceFiles =
fscArgs
|> Array.choose (fun (argument: string) ->
// We make an absolute path because the sarif report cannot deal properly with relative path.
let path = Path.Combine(Directory.GetCurrentDirectory(), argument)

if not (isFSharpFile path) || not (File.Exists path) then
None
else
Some path
)

let otherOptions = fscArgs |> Array.filter (fun line -> not (isFSharpFile line))

let projectOptions =
{
ProjectFileName = "Project"
ProjectId = None
SourceFiles = sourceFiles
OtherOptions = otherOptions
ReferencedProjects = [||]
IsIncompleteTypeCheckEnvironment = false
UseScriptResolutionRules = false
LoadTime = DateTime.Now
UnresolvedReferences = None
OriginalLoadReferences = []
Stamp = None
}

runProjectAux client projectOptions globs

let printMessages failOnWarnings (msgs: AnalyzerMessage list) =
if verbose then
printfn ""
Expand Down Expand Up @@ -219,7 +269,7 @@ let writeReport (results: AnalyzerMessage list option) (report: string) =

sarifLogger.Dispose()
with ex ->
let details = if not verbose then "" else $" %s{ex.Message}"
let details = if not verbose then "" else $" %A{ex}"
printfn $"Could not write sarif to %s{report}%s{details}"

let calculateExitCode failOnWarnings (msgs: AnalyzerMessage list option) : int =
Expand Down Expand Up @@ -302,20 +352,25 @@ let main argv =
printInfo "Registered %d analyzers from %d dlls" analyzers dlls

let projOpts = results.TryGetResult <@ Project @>
let fscArgs = results.TryGetResult <@ FSC_Args @>
let report = results.TryGetResult <@ Report @>

let results =
if analyzers = 0 then
Some []
else
match projOpts with
| None
| Some [] ->
match projOpts, fscArgs with
| None, None
| Some [], None ->
printError
"No project given. Use `--project PATH_TO_FSPROJ`. Pass path relative to current directory.%s"

None
| Some projects ->
| Some _, Some _ ->
printError "`--project` and `--fsc-args` cannot be combined."
exit 1
| None, Some fscArgs -> runFscArgs client fscArgs ignoreFiles |> Async.RunSynchronously
| Some projects, None ->
let runProj (proj: string) =
async {
let project =
Expand Down