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

Error when analyzer globs go unmatched #204

Closed
wants to merge 3 commits into from
Closed
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
118 changes: 86 additions & 32 deletions src/FSharp.Analyzers.Cli/Program.fs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
open System
open System.Collections.Generic
open System.IO
open System.Runtime.Loader
open System.Runtime.InteropServices
Expand Down Expand Up @@ -456,6 +457,32 @@ let getProperties (results: ParseResults<Arguments>) =
| _ -> ()
]

/// Returns a "does this string match any of these globs" function,
/// and also an IReadOnlyList you can use to determine whether across all invocations of the function,
/// any given glob was ever matched.
/// Note that the returned function will always scan over every element of the input list, so that it
/// can report the "did anything match this glob" correctly.
let createFilter (globs: string list) : (string -> bool) * IReadOnlyList<Glob * bool> =
let globs = globs |> List.map Glob

let unmatchedAnalyzerPatterns = ResizeArray()

globs |> Seq.map (fun glob -> glob, true) |> unmatchedAnalyzerPatterns.AddRange

let anyMatches (s: string) =
let mutable result = false

globs
|> List.iteri (fun index glob ->
if glob.IsMatch s then
unmatchedAnalyzerPatterns.[index] <- (glob, false)
result <- true
)

result

anyMatches, unmatchedAnalyzerPatterns :> _

[<EntryPoint>]
let main argv =
let toolsPath = Init.init (DirectoryInfo Environment.CurrentDirectory) None
Expand Down Expand Up @@ -555,24 +582,24 @@ let main argv =

logger.LogInformation("Loading analyzers from {0}", (String.concat ", " analyzersPaths))

let exclInclAnalyzers =
let exclInclAnalyzers, unmatchedAnalyzerPatterns =
let excludeAnalyzers = results.GetResult(<@ Exclude_Analyzers @>, [])
let includeAnalyzers = results.GetResult(<@ Include_Analyzers @>, [])

match excludeAnalyzers, includeAnalyzers with
| e, [] ->
fun (s: string) -> e |> List.map Glob |> List.exists (fun g -> g.IsMatch s)
|> ExcludeFilter
let result, list = createFilter e
ExcludeFilter result, list
| [], i ->
fun (s: string) -> i |> List.map Glob |> List.exists (fun g -> g.IsMatch s)
|> IncludeFilter
let result, list = createFilter i
IncludeFilter result, list
| _e, i ->
logger.LogWarning(
"--exclude-analyzers and --include-analyzers are mutually exclusive, ignoring --exclude-analyzers"
)

fun (s: string) -> i |> List.map Glob |> List.exists (fun g -> g.IsMatch s)
|> IncludeFilter
let result, list = createFilter i
IncludeFilter result, list

AssemblyLoadContext.Default.add_Resolving (fun _ctx assemblyName ->
if assemblyName.Name <> "FSharp.Core" then
Expand Down Expand Up @@ -634,36 +661,63 @@ let main argv =
|> List.concat
|> Some

match results with
| None -> -1
| Some results ->
let results, hasError =
match Result.allOkOrError results with
| Ok results -> results, false
| Error(results, _errors) -> results, true
let unmatchedAnalyzerPatterns =
unmatchedAnalyzerPatterns
|> Seq.choose (fun (glob, isUnmatched) -> if isUnmatched then Some glob else None)
|> Seq.toList

// Before we process the results, unconditionally warn if the inclusion or exclusion globs didn't look right.
// Then, *after* we've printed the results (which may be useful even if they're partial!), we'll fail if they
// didn't look right.
let anyUnmatchedAnalyzers =
if not (List.isEmpty unmatchedAnalyzerPatterns) then
logger.LogError(
"The following glob(s) were specified to include or exclude specific analyzers, but they did not match any discovered analyzers. Have you got them right? {UnmatchedAnalyzerGlobs}",
unmatchedAnalyzerPatterns |> Seq.map _.Pattern |> String.concat ", "
)

true
else
false

let results = results |> List.concat
let results =
match results with
| None -> exit -1
| Some results -> results

printMessages results
let results, hasError =
match Result.allOkOrError results with
| Ok results -> results, false
| Error(results, _errors) -> results, true

report |> Option.iter (writeReport results codeRoot)
let results = results |> List.concat

let check =
results
|> List.exists (fun analyzerMessage ->
let message = analyzerMessage.Message
printMessages results

message.Severity = Severity.Error
)
report |> Option.iter (writeReport results codeRoot)

if failedAssemblies > 0 then
logger.LogError(
"Because we failed to load some assemblies to obtain analyzers from them, exiting (failure count: {FailedAssemblyLoadCount})",
failedAssemblies
)
let check =
results
|> List.exists (fun analyzerMessage ->
let message = analyzerMessage.Message

exit -3
message.Severity = Severity.Error
)

if failedAssemblies > 0 then
logger.LogError(
"Because we failed to load some assemblies to obtain analyzers from them, exiting (failure count: {FailedAssemblyLoadCount})",
failedAssemblies
)

if check then -2
elif hasError then -4
else 0
exit -3

if anyUnmatchedAnalyzers then
logger.LogError("Aborting because there were unmatched analyzer globs (see earlier log).")
-5
elif check then
-2
elif hasError then
-4
else
0
Loading