Skip to content
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
3 changes: 2 additions & 1 deletion src/FSharp.Analyzers.Cli/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ let runProject
async {
logger.LogInformation("Checking project {0}", fsharpOptions.ProjectFileName)
let! checkProjectResults = fcs.ParseAndCheckProject(fsharpOptions)
let analyzerOptions = BackgroundCompilerOptions fsharpOptions

let! messagesPerAnalyzer =
fsharpOptions.SourceFiles
Expand Down Expand Up @@ -202,7 +203,7 @@ let runProject
let! parseAndCheckResults = fcs.GetBackgroundCheckResultsForFileInProject(fileName, fsharpOptions)

let ctx =
Utils.createContext checkProjectResults fileName sourceText parseAndCheckResults
Utils.createContext checkProjectResults fileName sourceText parseAndCheckResults analyzerOptions

logger.LogInformation("Running analyzers for {0}", ctx.FileName)
let! results = client.RunAnalyzers ctx
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ let getContextFor (opts: FSharpProjectOptions) isSignature source =
fcs.NotifyFileChanged(fileName, opts) |> Async.RunSynchronously // workaround for https://github.com/dotnet/fsharp/issues/15960
let checkProjectResults = fcs.ParseAndCheckProject(opts) |> Async.RunSynchronously
let allSymbolUses = checkProjectResults.GetAllUsesOfAllSymbols()
let analyzerOpts = BackgroundCompilerOptions opts

if Array.isEmpty allSymbolUses then
failwith "no symboluses"
Expand All @@ -266,7 +267,7 @@ let getContextFor (opts: FSharpProjectOptions) isSignature source =
raise (CompilerDiagnosticErrors diagErrors)

let sourceText = SourceText.ofString source
Utils.createContext checkProjectResults fileName sourceText (parseFileResults, checkFileResults)
Utils.createContext checkProjectResults fileName sourceText (parseFileResults, checkFileResults) analyzerOpts
| Error e -> failwith $"typechecking file failed: %O{e}"

let getContext (opts: FSharpProjectOptions) source = getContextFor opts false source
Expand Down
61 changes: 61 additions & 0 deletions src/FSharp.Analyzers.SDK/FSharp.Analyzers.SDK.fs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,24 @@ module EntityCache =
with _ ->
[]

[<AutoOpen>]
module Extensions =
open FSharp.Compiler.CodeAnalysis.ProjectSnapshot

type FSharpReferencedProjectSnapshot with

member x.ProjectFilePath =
match x with
| FSharpReferencedProjectSnapshot.FSharpReference(snapshot = snapshot) -> snapshot.ProjectFileName |> Some
| _ -> None

type FSharpReferencedProject with

member x.ProjectFilePath =
match x with
| FSharpReferencedProject.FSharpReference(options = options) -> options.ProjectFileName |> Some
| _ -> None

[<AbstractClass>]
[<AttributeUsage(AttributeTargets.Method ||| AttributeTargets.Property ||| AttributeTargets.Field)>]
type AnalyzerAttribute(name: string, shortDescription: string, helpUri: string) =
Expand Down Expand Up @@ -93,6 +111,45 @@ type EditorAnalyzerAttribute

type Context = interface end

type AnalyzerProjectOptions =
| BackgroundCompilerOptions of FSharpProjectOptions
| TransparentCompilerOptions of FSharpProjectSnapshot

member x.ProjectFileName =
match x with
| BackgroundCompilerOptions(options) -> options.ProjectFileName
| TransparentCompilerOptions(snapshot) -> snapshot.ProjectFileName

member x.ProjectId =
match x with
| BackgroundCompilerOptions(options) -> options.ProjectId
| TransparentCompilerOptions(snapshot) -> snapshot.ProjectId

member x.SourceFiles =
match x with
| BackgroundCompilerOptions(options) -> options.SourceFiles |> Array.toList
| TransparentCompilerOptions(snapshot) -> snapshot.SourceFiles |> List.map (fun f -> f.FileName)
|> List.map System.IO.Path.GetFullPath

member x.ReferencedProjectsPath =
match x with
| BackgroundCompilerOptions(options) ->
options.ReferencedProjects
|> Array.choose (fun p -> p.ProjectFilePath)
|> Array.toList
| TransparentCompilerOptions(snapshot) -> snapshot.ReferencedProjects |> List.choose (fun p -> p.ProjectFilePath)

member x.LoadTime =
match x with
| BackgroundCompilerOptions(options) -> options.LoadTime
| TransparentCompilerOptions(snapshot) -> snapshot.LoadTime

member x.OtherOptions =
match x with
| BackgroundCompilerOptions(options) -> options.OtherOptions |> Array.toList
| TransparentCompilerOptions(snapshot) -> snapshot.OtherOptions


type CliContext =
{
FileName: string
Expand All @@ -101,6 +158,7 @@ type CliContext =
CheckFileResults: FSharpCheckFileResults
TypedTree: FSharpImplementationFileContents option
CheckProjectResults: FSharpCheckProjectResults
ProjectOptions: AnalyzerProjectOptions
}

interface Context
Expand All @@ -122,6 +180,7 @@ type EditorContext =
CheckFileResults: FSharpCheckFileResults option
TypedTree: FSharpImplementationFileContents option
CheckProjectResults: FSharpCheckProjectResults option
ProjectOptions: AnalyzerProjectOptions
}

interface Context
Expand Down Expand Up @@ -196,6 +255,7 @@ module Utils =
(fileName: string)
(sourceText: ISourceText)
((parseFileResults: FSharpParseFileResults, checkFileResults: FSharpCheckFileResults))
(projectOptions: AnalyzerProjectOptions)
: CliContext
=
{
Expand All @@ -205,6 +265,7 @@ module Utils =
CheckFileResults = checkFileResults
TypedTree = checkFileResults.ImplementationFile
CheckProjectResults = checkProjectResults
ProjectOptions = projectOptions
}

let createFCS documentSource =
Expand Down
23 changes: 23 additions & 0 deletions src/FSharp.Analyzers.SDK/FSharp.Analyzers.SDK.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,24 @@ type EditorAnalyzerAttribute =
/// Marker interface which both the CliContext and EditorContext implement
type Context = interface end

/// Options related to the project being analyzed.
type AnalyzerProjectOptions =
| BackgroundCompilerOptions of FSharpProjectOptions
| TransparentCompilerOptions of FSharpProjectSnapshot

/// The current project name.
member ProjectFileName: string
/// The identifier of the current project.
member ProjectId: string option
/// The set of source files in the current project.
member SourceFiles: string list
/// Projects referenced by this project.
member ReferencedProjectsPath: string list
/// The time at which the project was loaded.
member LoadTime: DateTime
/// Additional command line argument options for the project.
member OtherOptions: string list

/// All the relevant compiler information for a given file.
/// Contains the source text, untyped and typed tree information.
type CliContext =
Expand All @@ -69,6 +87,8 @@ type CliContext =
/// 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
/// Options related to the project being analyzed.
ProjectOptions: AnalyzerProjectOptions
}

interface Context
Expand Down Expand Up @@ -101,6 +121,8 @@ type EditorContext =
/// 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 option
// Options related to the project being analyzed.
ProjectOptions: AnalyzerProjectOptions
}

interface Context
Expand Down Expand Up @@ -184,4 +206,5 @@ module Utils =
fileName: string ->
sourceText: ISourceText ->
parseFileResults: FSharpParseFileResults * checkFileResults: FSharpCheckFileResults ->
projectOptions: AnalyzerProjectOptions ->
CliContext