Skip to content

Commit c49d6e9

Browse files
authored
Merge pull request #194 from dawedawe/support_include_analyzers
Support include analyzers and make life simpler for editor clients
2 parents d739236 + 3dfddfe commit c49d6e9

File tree

5 files changed

+63
-25
lines changed

5 files changed

+63
-25
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
99

1010
### Changed
1111
* [Add missing TAST walkers](https://github.com/ionide/FSharp.Analyzers.SDK/pull/185) (thanks @dawedawe!)
12+
* [Add support for --include-analyzers to ignore all others](https://github.com/ionide/FSharp.Analyzers.SDK/pull/194) (thanks @dawedawe!)
1213

1314
## [0.22.0] - 2023-12-19
1415

Directory.Packages.props

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
<PackageVersion Include="Microsoft.Build.Locator" Version="1.4.1" />
2020
<!-- Need to update Directory.Build.props DotNet.ReproducibleBuilds.Isolated version when updating this-->
2121
<PackageVersion Include="DotNet.ReproducibleBuilds" Version="1.1.1" PrivateAssets="All" />
22-
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
23-
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
24-
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
22+
<PackageVersion Include="Microsoft.Extensions.Logging" Version="6.0.0" />
23+
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
24+
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
2525
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
2626
<PackageVersion Include="MSBuild.StructuredLogger" Version="2.1.815" />
2727
<PackageVersion Include="NUnit" Version="3.13.3" />

src/FSharp.Analyzers.Cli/Program.fs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type Arguments =
2828
| [<Unique>] Treat_As_Error of string list
2929
| [<Unique>] Ignore_Files of string list
3030
| [<Unique>] Exclude_Analyzer of string list
31+
| [<Unique>] Include_Analyzer of string list
3132
| [<Unique>] Report of string
3233
| [<Unique>] FSC_Args of string
3334
| [<Unique>] Code_Root of string
@@ -53,6 +54,8 @@ type Arguments =
5354
"List of analyzer codes that should be treated as severity Error by the tool. Regardless of the original severity."
5455
| Ignore_Files _ -> "Source files that shouldn't be processed."
5556
| Exclude_Analyzer _ -> "The names of analyzers that should not be executed."
57+
| Include_Analyzer _ ->
58+
"The names of analyzers that should exclusively be executed while all others are ignored. Takes precedence over --exclude-analyzer."
5659
| Report _ -> "Write the result messages to a (sarif) report file."
5760
| Verbosity _ ->
5861
"The verbosity level. The available verbosity levels are: n[ormal], d[etailed], diag[nostic]."
@@ -531,7 +534,19 @@ let main argv =
531534

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

534-
let excludeAnalyzers = results.GetResult(<@ Exclude_Analyzer @>, [])
537+
let includeExclude =
538+
let excludeAnalyzers = results.GetResult(<@ Exclude_Analyzer @>, [])
539+
let includeAnalyzers = results.GetResult(<@ Include_Analyzer @>, [])
540+
541+
match excludeAnalyzers, includeAnalyzers with
542+
| e, [] -> Exclude(Set.ofList e)
543+
| [], i -> Include(Set.ofList i)
544+
| i, _e ->
545+
logger.LogWarning(
546+
"--exclude-analyzers and --include-analyzers are mutually exclusive, ignoring --exclude-analyzers"
547+
)
548+
549+
Include(Set.ofList i)
535550

536551
AssemblyLoadContext.Default.add_Resolving (fun _ctx assemblyName ->
537552
if assemblyName.Name <> "FSharp.Core" then
@@ -548,13 +563,12 @@ let main argv =
548563
exit 1
549564
)
550565

551-
let client =
552-
Client<CliAnalyzerAttribute, CliContext>(logger, Set.ofList excludeAnalyzers)
566+
let client = Client<CliAnalyzerAttribute, CliContext>(logger)
553567

554568
let dlls, analyzers =
555569
((0, 0), analyzersPaths)
556570
||> List.fold (fun (accDlls, accAnalyzers) analyzersPath ->
557-
let dlls, analyzers = client.LoadAnalyzers analyzersPath
571+
let dlls, analyzers = client.LoadAnalyzers(analyzersPath, includeExclude)
558572
(accDlls + dlls), (accAnalyzers + analyzers)
559573
)
560574

src/FSharp.Analyzers.SDK/FSharp.Analyzers.SDK.Client.fs

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -127,17 +127,19 @@ module Client =
127127
|> Seq.choose (analyzerFromMember<'TAnalyzerAttribute, 'TContext> path)
128128
|> Seq.toList
129129

130-
type Client<'TAttribute, 'TContext when 'TAttribute :> AnalyzerAttribute and 'TContext :> Context>
131-
(logger: ILogger, excludedAnalyzers: string Set)
132-
=
130+
type ExcludeInclude =
131+
| Exclude of string Set
132+
| Include of string Set
133+
134+
type Client<'TAttribute, 'TContext when 'TAttribute :> AnalyzerAttribute and 'TContext :> Context>(logger: ILogger) =
133135
do TASTCollecting.logger <- logger
134136

135137
let registeredAnalyzers =
136138
ConcurrentDictionary<string, Client.RegisteredAnalyzer<'TContext> list>()
137139

138-
new() = Client(Abstractions.NullLogger.Instance, Set.empty)
140+
new() = Client(Abstractions.NullLogger.Instance)
139141

140-
member x.LoadAnalyzers(dir: string) : int * int =
142+
member x.LoadAnalyzers(dir: string, ?excludeInclude: ExcludeInclude) : int * int =
141143
if Directory.Exists dir then
142144
let analyzerAssemblies =
143145
let regex = Regex(@".*test.*\.dll$")
@@ -184,7 +186,7 @@ type Client<'TAttribute, 'TContext when 'TAttribute :> AnalyzerAttribute and 'TC
184186
true
185187
else
186188
logger.LogError(
187-
"Trying to load {0} which was built using SDK version {1}. Expect {2} instead. Assembly will be skipped.",
189+
"Trying to load {Name} which was built using SDK version {Version}. Expect {SdkVersion} instead. Assembly will be skipped.",
188190
name,
189191
version,
190192
Utils.currentFSharpAnalyzersSDKVersion
@@ -197,16 +199,30 @@ type Client<'TAttribute, 'TContext when 'TAttribute :> AnalyzerAttribute and 'TC
197199
assembly.GetExportedTypes()
198200
|> Seq.collect (Client.analyzersFromType<'TAttribute, 'TContext> path)
199201
|> Seq.filter (fun registeredAnalyzer ->
200-
let shouldExclude = excludedAnalyzers.Contains(registeredAnalyzer.Name)
201-
202-
if shouldExclude then
203-
logger.LogInformation(
204-
"Excluding {0} from {1}",
205-
registeredAnalyzer.Name,
206-
assembly.FullName
207-
)
208-
209-
not shouldExclude
202+
match excludeInclude with
203+
| Some(Exclude excluded) ->
204+
let shouldExclude = excluded.Contains(registeredAnalyzer.Name)
205+
206+
if shouldExclude then
207+
logger.LogInformation(
208+
"Excluding {Name} from {FullName}",
209+
registeredAnalyzer.Name,
210+
assembly.FullName
211+
)
212+
213+
not shouldExclude
214+
| Some(Include included) ->
215+
let shouldInclude = included.Contains(registeredAnalyzer.Name)
216+
217+
if shouldInclude then
218+
logger.LogInformation(
219+
"Including {Name} from {FullName}",
220+
registeredAnalyzer.Name,
221+
assembly.FullName
222+
)
223+
224+
shouldInclude
225+
| None -> true
210226
)
211227
|> Seq.toList
212228

src/FSharp.Analyzers.SDK/FSharp.Analyzers.SDK.Client.fsi

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,22 @@ type AnalysisResult =
88
Output: Result<Message list, exn>
99
}
1010

11+
type ExcludeInclude =
12+
/// Analyzers in this set should be ignored.
13+
| Exclude of string Set
14+
/// Analyzers in this set should be used exclusively, while all others are ignored.
15+
| Include of string Set
16+
1117
type Client<'TAttribute, 'TContext when 'TAttribute :> AnalyzerAttribute and 'TContext :> Context> =
12-
new: logger: ILogger * excludedAnalyzers: string Set -> Client<'TAttribute, 'TContext>
18+
new: logger: ILogger -> Client<'TAttribute, 'TContext>
1319
new: unit -> Client<'TAttribute, 'TContext>
1420
/// <summary>
1521
/// Loads into private state any analyzers defined in any assembly
1622
/// matching `*Analyzer*.dll` in given directory (and any subdirectories)
23+
/// Analyzers are filtered according to the ExcludeInclude set, if provided.
1724
/// </summary>
1825
/// <returns>number of found dlls matching `*Analyzer*.dll` and number of registered analyzers</returns>
19-
member LoadAnalyzers: dir: string -> int * int
26+
member LoadAnalyzers: dir: string * ?excludeInclude: ExcludeInclude -> int * int
2027
/// <summary>Runs all registered analyzers for given context (file).</summary>
2128
/// <returns>list of messages. Ignores errors from the analyzers</returns>
2229
member RunAnalyzers: ctx: 'TContext -> Async<AnalyzerMessage list>

0 commit comments

Comments
 (0)