Skip to content

Commit

Permalink
get end-to-end analyzer code working again
Browse files Browse the repository at this point in the history
  • Loading branch information
baronfel committed Mar 8, 2020
1 parent cc3351c commit 0373f04
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 34 deletions.
13 changes: 6 additions & 7 deletions src/FsAutoComplete.Core/Commands.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ open Utils
open FSharp.Compiler.Range
open ProjectSystem



[<RequireQualifiedAccess>]
type LocationResponse<'a,'b> =
| Use of 'a
Expand All @@ -32,10 +30,10 @@ type CoreResponse<'a> =
| Res of 'a

[<RequireQualifiedAccess>]
type NotificationEvent =
type NotificationEvent<'analyzer> =
| ParseError of errors: FSharpErrorInfo[] * file: string
| Workspace of ProjectSystem.ProjectResponse
| AnalyzerMessage of messages: obj * file: string
| AnalyzerMessage of messages: 'analyzer [] * file: string
| UnusedOpens of file: string * opens: range[]
| Lint of file: string * warningsWithCodes: Lint.EnrichedLintWarning list
| UnusedDeclarations of file: string * decls: (range * bool)[]
Expand All @@ -44,7 +42,7 @@ type NotificationEvent =
| Diagnostics of LanguageServerProtocol.Types.PublishDiagnosticsParams
| FileParsed of string

type Commands (serialize : Serializer, backgroundServiceEnabled) =
type Commands<'analyzer> (serialize : Serializer, backgroundServiceEnabled) =
let checker = FSharpCompilerServiceChecker(backgroundServiceEnabled)
let state = State.Initial (checker.GetFSharpChecker())
let fileParsed = Event<FSharpParseFileResults>()
Expand All @@ -55,9 +53,9 @@ type Commands (serialize : Serializer, backgroundServiceEnabled) =
let mutable linterConfiguration: FSharpLint.Application.Lint.ConfigurationParam = FSharpLint.Application.Lint.ConfigurationParam.Default
let mutable lastVersionChecked = -1
let mutable lastCheckResult : ParseAndCheckResults option = None
let mutable analyzerHandler : ((string * string [] * FSharp.Compiler.Ast.ParsedInput * FSharpImplementationFileContents * FSharpEntity list * (bool -> AssemblySymbol list)) -> obj) option = None
let mutable analyzerHandler : ((string * string [] * FSharp.Compiler.Ast.ParsedInput * FSharpImplementationFileContents * FSharpEntity list * (bool -> AssemblySymbol list)) -> 'analyzer []) option = None

let notify = Event<NotificationEvent>()
let notify = Event<NotificationEvent<_>>()

let fileStateSet = Event<unit>()
let commandsLogger = LogProvider.getLoggerByName "Commands"
Expand Down Expand Up @@ -135,6 +133,7 @@ type Commands (serialize : Serializer, backgroundServiceEnabled) =
match parseAndCheck.GetParseResults.ParseTree, parseAndCheck.GetCheckResults.ImplementationFile with
| Some pt, Some tast ->
let res = handler (file, state.Files.[file].Lines, pt, tast, parseAndCheck.GetCheckResults.PartialAssemblySignature.Entities |> Seq.toList, parseAndCheck.GetAllEntities)

(res, file)
|> NotificationEvent.AnalyzerMessage
|> notify.Trigger
Expand Down
12 changes: 9 additions & 3 deletions src/FsAutoComplete/FsAutoComplete.Lsp.fs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ type FSharpLspClient(sendServerRequest: ClientNotificationSender) =
// TODO: Add the missing notifications
// TODO: Implement requests

type Commands =
#if ANALYZER_SUPPORT
Commands<SDK.Message>
#else
Commands<obj>
#endif

type FsharpLspServer(commands: Commands, lspClient: FSharpLspClient) =
inherit LspServer()

Expand Down Expand Up @@ -301,7 +308,6 @@ type FsharpLspServer(commands: Commands, lspClient: FSharpLspClient) =
|> Async.Start
| NotificationEvent.AnalyzerMessage(messages, file) ->
#if ANALYZER_SUPPORT
let messages = messages :?> SDK.Message []
let uri = filePathToUri file
diagnosticCollections.AddOrUpdate((uri, "F# Analyzers"), [||], fun _ _ -> [||]) |> ignore
let fs =
Expand Down Expand Up @@ -455,14 +461,14 @@ type FsharpLspServer(commands: Commands, lspClient: FSharpLspClient) =
try
SDK.Client.runAnalyzersSafely ctx
|> List.collect extractResultsFromAnalyzer
|> box
|> List.toArray
with
| ex ->
Loggers.analyzers.error (Log.setMessage "Error while processing analyzers for {file}: {message}"
>> Log.addContextDestructured "message" ex.Message
>> Log.addExn ex
>> Log.addContextDestructured "file" file)
box []
[||]
commands.AnalyzerHandler <- Some analyzerHandler
#endif
let c =
Expand Down
8 changes: 8 additions & 0 deletions src/FsAutoComplete/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ open Serilog.Core
open Serilog.Events
open FsAutoComplete.Logging

type Commands =
#if ANALYZER_SUPPORT
Commands<FSharp.Analyzers.SDK.Message>
#else
Commands<obj>
#endif


[<EntryPoint>]
let entry args =

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module AnalzyersTest

let sampleOption = None
let sampleOption: int option = None
printfn "%d" sampleOption.Value
2 changes: 1 addition & 1 deletion test/FsAutoComplete.Tests.Lsp/Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1055,7 +1055,7 @@ let analyzerTests =
let serverTest f () = f serverStart.Value

testList "analyzer integration" [
ftestCase "can run analyzer on file" (serverTest (fun (server, events, rootPath, testFilePath) ->
testCase "can run analyzer on file" (serverTest (fun (server, events, rootPath, testFilePath) ->
do server.TextDocumentDidOpen { TextDocument = loadDocument testFilePath } |> Async.RunSynchronously
// now wait for analyzer events for the file:

Expand Down
49 changes: 31 additions & 18 deletions test/OptionAnalyzer/Analyzer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ open System
open FSharp.Analyzers.SDK
open FSharp.Compiler.SourceCodeServices
open FSharp.Compiler.Range
open FsAutoComplete.Logging

let rec visitExpr memberCallHandler (e:FSharpExpr) =
match e with
Expand Down Expand Up @@ -116,23 +117,35 @@ let notUsed() =
let option : Option<int> = None
option.Value

let logger = LogProvider.getLoggerByName "OptionAnalyzer"

let info message items =
let mutable log = Log.setMessage message
for (name, value) in items do
log <- log >> Log.addContextDestructured name value
logger.info log

let inline (==>) x y = x, box y

[<Analyzer "OptionAnalyzer">]
let optionValueAnalyzer : Analyzer =
fun ctx ->
let state = ResizeArray<range>()
let handler (range: range) (m: FSharpMemberOrFunctionOrValue) =
let name = String.Join(".", m.DeclaringEntity.Value.FullName, m.DisplayName)
if name = "Microsoft.FSharp.Core.FSharpOption`1.Value" then
state.Add range
ctx.TypedTree.Declarations |> List.iter (visitDeclaration handler)
state
|> Seq.map (fun r ->
{ Type = "Option.Value analyzer"
Message = "Option.Value shouldn't be used"
Code = "OV001"
Severity = Warning
Range = r
Fixes = []}

)
|> Seq.toList
fun ctx ->
info "analyzing {file} for uses of Option.Value" [ "file" ==> ctx.FileName ]
let state = ResizeArray<range>()
let handler (range: range) (m: FSharpMemberOrFunctionOrValue) =
let rangeString = sprintf "(%d,%d)-(%d,%d)" range.Start.Line range.Start.Column range.End.Line range.End.Column
let name = String.Join(".", m.DeclaringEntity.Value.FullName, m.DisplayName)
info "checking value at {range} with name {name}" [ "range" ==> rangeString
"name" ==> name ]
if name = "Microsoft.FSharp.Core.FSharpOption`1.Value" then
info "matched at range {range}" [ "range" ==> rangeString ]
state.Add range
ctx.TypedTree.Declarations |> List.iter (visitDeclaration handler)
state
|> Seq.map (fun r -> { Type = "Option.Value analyzer"
Message = "Option.Value shouldn't be used"
Code = "OV001"
Severity = Warning
Range = r
Fixes = [] })
|> Seq.toList
11 changes: 7 additions & 4 deletions test/OptionAnalyzer/OptionAnalyzer.fsproj
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../../src/FsAutoComplete.Logging/FsAutoComplete.Logging.fsproj">
<Name>FsAutoComplete.Logging.fsproj</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="Analyzer.fs" />
</ItemGroup>
<Import Project="..\..\.paket\Paket.Restore.targets" />
</Project>
</Project>

0 comments on commit 0373f04

Please sign in to comment.