Skip to content

Commit

Permalink
Merge pull request #92 from nojaf/optional-typed-tree
Browse files Browse the repository at this point in the history
Make TypedTree optional in CliContext.
  • Loading branch information
nojaf authored Sep 18, 2023
2 parents f52b7af + 5b026d5 commit 2d788e9
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 28 deletions.
4 changes: 3 additions & 1 deletion samples/OptionAnalyzer/Library.fs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ let optionValueAnalyzer: Analyzer<CliContext> =
if name = "Microsoft.FSharp.Core.FSharpOption`1.Value" then
state.Add range

ctx.TypedTree.Declarations |> List.iter (visitDeclaration handler)
match ctx.TypedTree with
| None -> ()
| Some typedTree -> typedTree.Declarations |> List.iter (visitDeclaration handler)

return
state
Expand Down
31 changes: 11 additions & 20 deletions src/FSharp.Analyzers.Cli/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -79,22 +79,16 @@ let createContext
(fileName: string)
(sourceText: ISourceText)
((parseFileResults: FSharpParseFileResults, checkFileResults: FSharpCheckFileResults))
: CliContext option
: CliContext
=
match checkFileResults.ImplementationFile with
| Some tast ->
let context: CliContext =
{
FileName = fileName
SourceText = sourceText
ParseFileResults = parseFileResults
CheckFileResults = checkFileResults
TypedTree = tast
CheckProjectResults = checkProjectResults
}

Some context
| _ -> None
{
FileName = fileName
SourceText = sourceText
ParseFileResults = parseFileResults
CheckFileResults = checkFileResults
TypedTree = checkFileResults.ImplementationFile
CheckProjectResults = checkProjectResults
}

let runProject (client: Client<CliAnalyzerAttribute, CliContext>) toolsPath proj (globs: Glob list) =
async {
Expand All @@ -119,11 +113,8 @@ let runProject (client: Client<CliAnalyzerAttribute, CliContext>) toolsPath proj
|> Option.map (createContext checkProjectResults fileName sourceText)
)
|> Array.map (fun ctx ->
match ctx with
| Some c ->
printInfo "Running analyzers for %s" c.FileName
client.RunAnalyzers c
| None -> failwithf "could not get context for file %s" path
printInfo "Running analyzers for %s" ctx.FileName
client.RunAnalyzers ctx
)
|> Async.Parallel

Expand Down
22 changes: 18 additions & 4 deletions src/FSharp.Analyzers.SDK/FSharp.Analyzers.SDK.Client.fs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,23 @@ module Client =
let inline unboxAnalyzer v =
if isNull v then failwith "Analyzer is null" else unbox v

let hasExpectReturnType (t: Type) =
// t might be a System.RunTimeType as could have no FullName
if not (isNull t.FullName) then
t.FullName.StartsWith
"Microsoft.FSharp.Control.FSharpAsync`1[[Microsoft.FSharp.Collections.FSharpList`1[[FSharp.Analyzers.SDK.Message"
elif t.Name = "FSharpAsync`1" && t.GenericTypeArguments.Length = 1 then
let listType = t.GenericTypeArguments.[0]

if listType.Name = "FSharpList`1" && listType.GenericTypeArguments.Length = 1 then
// This could still be generic, as in an empty list is returned from the analyzer
let msgType = listType.GenericTypeArguments.[0]
msgType.Name = "a" || msgType = typeof<Message>
else
false
else
false

let getAnalyzerFromMemberInfo mi =
match box mi with
| :? FieldInfo as m ->
Expand All @@ -37,10 +54,7 @@ module Client =
| :? MethodInfo as m ->
if m.ReturnType = typeof<Analyzer<'TContext>> then
Some(m.Invoke(null, null) |> unboxAnalyzer)
elif
m.ReturnType.FullName.StartsWith
"Microsoft.FSharp.Control.FSharpAsync`1[[Microsoft.FSharp.Collections.FSharpList`1[[FSharp.Analyzers.SDK.Message"
then
elif hasExpectReturnType m.ReturnType then
try
let analyzer: Analyzer<'TContext> = fun ctx -> m.Invoke(null, [| ctx |]) |> unbox
Some analyzer
Expand Down
2 changes: 1 addition & 1 deletion src/FSharp.Analyzers.SDK/FSharp.Analyzers.SDK.fs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ type CliContext =
SourceText: ISourceText
ParseFileResults: FSharpParseFileResults
CheckFileResults: FSharpCheckFileResults
TypedTree: FSharpImplementationFileContents
TypedTree: FSharpImplementationFileContents option
CheckProjectResults: FSharpCheckProjectResults
}

Expand Down
5 changes: 3 additions & 2 deletions src/FSharp.Analyzers.SDK/FSharp.Analyzers.SDK.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ type CliContext =
/// A handle to the results of CheckFileInProject.
/// See <a href="https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-codeanalysis-fsharpcheckfileresults.html">FSharpCheckFileResults Type</a>
CheckFileResults: FSharpCheckFileResults
/// Represents the definitional contents of a single file or fragment in an assembly, as seen by the F# language
/// Represents the definitional contents of a single file or fragment in an assembly, as seen by the F# language.
/// Only available for implementation files.
/// See <a href="https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-symbols-fsharpimplementationfilecontents.html">FSharpImplementationFileContents Type</a>
TypedTree: FSharpImplementationFileContents
TypedTree: FSharpImplementationFileContents option
/// A handle to the results of the entire project
/// See <a href="https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-codeanalysis-fsharpcheckprojectresults.html">FSharpCheckProjectResults Type</a>
CheckProjectResults: FSharpCheckProjectResults
Expand Down

0 comments on commit 2d788e9

Please sign in to comment.