Skip to content

Commit

Permalink
Merge pull request #143 from ionide/master
Browse files Browse the repository at this point in the history
Update FSharpLint version and add endpoint for F1 Help
  • Loading branch information
rneatherway authored Jan 19, 2017
2 parents ec6222a + a419644 commit faf516e
Show file tree
Hide file tree
Showing 13 changed files with 221 additions and 110 deletions.
14 changes: 7 additions & 7 deletions paket.lock
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
FRAMEWORK: NET45
NUGET
remote: https://www.nuget.org/api/v2
FAKE (4.43)
FAKE (4.47.2)
FParsec (1.0.2)
FSharp.Compiler.Service (8.0) - framework: >= net45
FSharp.Compiler.Service (8.0)
System.Collections.Immutable (>= 1.2)
System.Reflection.Metadata (>= 1.4.1-beta-24227-04)
FSharp.Compiler.Service.ProjectCracker (8.0)
FSharp.Core (4.0.0.1) - redirects: on
FSharpLint.Core (0.4.10)
FSharpLint.Core (0.5.1-beta)
FParsec (>= 1.0.2)
FSharp.Compiler.Service (>= 8.0)
FSharp.Compiler.Service.ProjectCracker (>= 8.0)
Expand All @@ -32,10 +32,10 @@ NUGET
Octokit (0.23)
Suave (1.1.3)
FSharp.Core (>= 3.1.2.5)
System.Collections.Immutable (1.3.0-preview1-24530-04)
System.Reflection.Metadata (1.4.1-preview1-24530-04)
System.Collections.Immutable (>= 1.3.0-preview1-24530-04)
System.Collections.Immutable (1.3)
System.Reflection.Metadata (1.4.1)
System.Collections.Immutable (>= 1.3)
GITHUB
remote: fsharp/FAKE
modules/Octokit/Octokit.fsx (da711ab136889bead398d5ac1a10dc53e60a2c87)
modules/Octokit/Octokit.fsx (be6e4b2b513b5f2cd64ec689fe7f1f45c39f4e92)
Octokit (>= 0.20)
5 changes: 4 additions & 1 deletion src/FsAutoComplete.Core/CommandResponse.fs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ module CommandResponse =
IsFromType = su.IsFromType } ] |> Seq.distinct |> Seq.toList }
serialize { Kind = "symboluse"; Data = su }

let help (serialize : Serializer) (data : string) =
serialize { Kind = "help"; Data = data }

let methods (serialize : Serializer) (meth: FSharpMethodGroup, commas: int) =
serialize { Kind = "method"
Data = { Name = meth.MethodName
Expand Down Expand Up @@ -382,4 +385,4 @@ module CommandResponse =
Word = word
}

serialize { Kind = "namespaces"; Data = data}
serialize { Kind = "namespaces"; Data = data}
57 changes: 32 additions & 25 deletions src/FsAutoComplete.Core/Commands.fs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@ type Commands (serialize : Serializer) =
return! parse' file text checkOptions
}

member __.ParseAllInBackground () =
do checker.ParseAndCheckAllProjectsInBackground (state.FileCheckOptions.ToSeq() |> Seq.map snd)
[Response.errors serialize ([||], "") ]
member __.ParseAndCheckProjectsInBackgroundForFile file = async {
do checker.CheckProjectsInBackgroundForFile (file, state.FileCheckOptions.ToSeq() )
return [Response.errors serialize ([||], "") ]
}

member __.ParseProjectsForFile file = async {
let! res = checker.ParseProjectsForFile(file, state.FileCheckOptions.ToSeq())
Expand All @@ -74,19 +75,21 @@ type Commands (serialize : Serializer) =
[ Response.errors serialize (errors, file)]
}

member __.FileChecked =
checker.FileChecked
|> Event.map (fun fn ->
let file = Path.GetFullPath fn
let res = state.FileCheckOptions |> Seq.tryFind (fun kv -> Path.GetFullPath kv.Key = file)
match res with
| None -> async { return [Response.info serialize ( sprintf "Project for file not found: %s" file) ] }
| Some kv ->
async {
let! (_, checkResults) = checker.GetBackgroundCheckResultsForFileInProject(fn, kv.Value)
return [ Response.errors serialize (checkResults.Errors, file) ] })


// member __.FileChecked =
// checker.FileChecked
// |> Event.map (fun fn ->
// let file = Path.GetFullPath fn
// let res = state.FileCheckOptions |> Seq.tryFind (fun kv -> Path.GetFullPath kv.Key = file)
// match res with
// | None -> async { return [Response.info serialize ( sprintf "Project for file not found: %s" file) ] }
// | Some kv ->
// async {
// let result= checker.TryGetRecentCheckResultsForFile(fn, kv.Value)
// return
// match result with
// | None -> [Response.info serialize "File not parsed"]
// | Some res -> [ Response.errors serialize (res.GetCheckResults.Errors, file) ]
// })

member __.Project projectFileName verbose onChange = async {
let projectFileName = Path.GetFullPath projectFileName
Expand Down Expand Up @@ -200,6 +203,9 @@ type Commands (serialize : Serializer) =
member x.SymbolUse (tyRes : ParseAndCheckResults) (pos: Pos) lineStr =
tyRes.TryGetSymbolUse pos lineStr |> x.SerializeResult Response.symbolUse

member x.Help (tyRes : ParseAndCheckResults) (pos: Pos) lineStr =
tyRes.TryGetF1Help pos lineStr |> x.SerializeResult Response.help

member x.SymbolUseProject (tyRes : ParseAndCheckResults) (pos: Pos) lineStr =
let fn = tyRes.FileName
tyRes.TryGetSymbolUse pos lineStr |> x.SerializeResultAsync (fun _ (sym, usages) ->
Expand Down Expand Up @@ -255,15 +261,6 @@ type Commands (serialize : Serializer) =
}

member __.GetNamespaceSuggestions (tyRes : ParseAndCheckResults) (pos: Pos) (line: LineStr) = async {
let! entitiesRes = tyRes.GetAllEntities ()
let symbol = Lexer.getSymbol pos.Line pos.Col line SymbolLookupKind.Fuzzy [||]

match symbol with
| None -> return [Response.info serialize "Symbol at position not found"]
| Some sym ->
match entitiesRes with
| None -> return [Response.info serialize "Something went wrong"]
| Some entities ->
match tyRes.GetAST with
| None -> return [Response.info serialize "Parsed Tree not avaliable"]
| Some parsedTree ->
Expand All @@ -273,6 +270,16 @@ type Commands (serialize : Serializer) =
match ParsedInput.getEntityKind parsedTree pos with
| None -> return [Response.info serialize "EntityKind not found"]
| Some entityKind ->

let symbol = Lexer.getSymbol pos.Line pos.Col line SymbolLookupKind.Fuzzy [||]
match symbol with
| None -> return [Response.info serialize "Symbol at position not found"]
| Some sym ->

let! entitiesRes = tyRes.GetAllEntities ()
match entitiesRes with
| None -> return [Response.info serialize "Something went wrong"]
| Some entities ->
let isAttribute = entityKind = EntityKind.Attribute
let entities =
entities |> List.filter (fun e ->
Expand Down
20 changes: 15 additions & 5 deletions src/FsAutoComplete.Core/CompilerServiceInterface.fs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,17 @@ type ParseAndCheckResults
let! symboluses = checkResults.GetUsesOfSymbolInFile symboluse.Symbol
return Success (symboluse, symboluses) }

member __.TryGetF1Help (pos: Pos) (lineStr: LineStr) =
async {
match Parsing.findLongIdents(pos.Col - 1, lineStr) with
| None -> return (Failure "No ident at this location")
| Some(colu, identIsland) ->

let! help = checkResults.GetF1KeywordAlternate(pos.Line, colu, lineStr, identIsland)
match help with
| None -> return (Failure "No symbol information found")
| Some hlp -> return Success hlp}

member __.TryGetCompletions (pos: Pos) (lineStr: LineStr) filter = async {
let longName, residue = Parsing.findLongIdentsAndResidue(pos.Col - 1, lineStr)
try
Expand Down Expand Up @@ -150,7 +161,7 @@ type FSharpCompilerServiceChecker() =
let checker =
FSharpChecker.Create(
projectCacheSize = 200,
keepAllBackgroundResolutions = true,
keepAllBackgroundResolutions = false,
keepAssemblyContents = true)

let files = ConcurrentDictionary<string, Version * FileState>()
Expand Down Expand Up @@ -234,10 +245,9 @@ type FSharpCompilerServiceChecker() =
return { rawOptions with OtherOptions = opts }
}

member __.ParseAndCheckAllProjectsInBackground (options : FSharpProjectOptions seq) =
options
|> Seq.distinctBy(fun v -> v.ProjectFileName)
|> Seq.iter (checker.CheckProjectInBackground)
member __.CheckProjectsInBackgroundForFile (file,options : seq<string * FSharpProjectOptions>) =
defaultArg (getDependingProjects file options) []
|> List.iter (checker.CheckProjectInBackground)

member __.ParseProjectsForFile(file, options : seq<string * FSharpProjectOptions> ) =
let project = options |> Seq.tryFind (fun (k,_) -> k = file)
Expand Down
12 changes: 1 addition & 11 deletions src/FsAutoComplete.Core/FsAutoComplete.Core.fsproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Name>FsAutoComplete.Core</Name>
Expand Down Expand Up @@ -112,16 +112,6 @@
<Private>True</Private>
<Paket>True</Paket>
</Reference>
<Reference Include="FSharp.Compiler.Service.MSBuild.v12">
<HintPath>..\..\packages\FSharp.Compiler.Service\lib\net45\stock\FSharp.Compiler.Service.MSBuild.v12.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
<Reference Include="FSharp.Compiler.Service">
<HintPath>..\..\packages\FSharp.Compiler.Service\lib\net45\stock\FSharp.Compiler.Service.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
Expand Down
5 changes: 3 additions & 2 deletions src/FsAutoComplete.Core/paket.references
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
FSharpLint.Core
FSharp.Compiler.Service.ProjectCracker
FSharp.Compiler.Service.ProjectCracker
FSharp.Compiler.Service
FSharpLint.Core
1 change: 0 additions & 1 deletion src/FsAutoComplete.Suave/AssemblyInfo.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@ module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FsAutoComplete.Suave"
let [<Literal>] AssemblyProduct = "FsAutoComplete.Suave"
let [<Literal>] AssemblyDescription = "A Suave web server for interfacing with FSharp.Compiler.Service over a HTTP."

let [<Literal>] AssemblyVersion = "0.30.2"
let [<Literal>] AssemblyFileVersion = "0.30.2"
28 changes: 13 additions & 15 deletions src/FsAutoComplete.Suave/FsAutoComplete.Suave.fs
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,15 @@ let main argv =
let fs = new FileSystem(originalFs, commands.Files.TryFind)
AbstractIL.Internal.Library.Shim.FileSystem <- fs

commands.FileChecked
|> Event.add (fun response ->
client |> Option.iter (fun socket ->
async {
let! res = response
let cnt = res |> List.toArray |> Json.toJson
return! socket.send Text cnt true
} |> Async.Ignore |> Async.Start ))
// commands.FileChecked
// |> Event.add (fun response ->
// client |> Option.iter (fun socket ->
// async {
// let! res = response

// let cnt = res |> List.toArray |> Json.toJson
// return! socket.send Text cnt true
// } |> Async.Ignore |> Async.Start ))

let handler f : WebPart = fun (r : HttpContext) -> async {
let data = r.request |> getResourceFromReq
Expand Down Expand Up @@ -109,16 +110,11 @@ let main argv =

let app =
choose [
path "/notify" >=> handShake echo
// path "/notify" >=> handShake echo
path "/parse" >=> handler (fun (data : ParseRequest) -> commands.Parse data.FileName data.Lines data.Version)
path "/parseProjects" >=> handler (fun (data : ProjectRequest) -> commands.ParseProjectsForFile data.FileName)
//TODO: Add filewatcher
path "/parseProjectsInBackground" >=> fun httpCtx ->
async {
let errors = commands.ParseAllInBackground()
let res = errors |> List.toArray |> Json.toJson
return! Response.response HttpCode.HTTP_200 res httpCtx
}
path "/parseProjectsInBackground" >=> handler (fun (data : ProjectRequest) -> commands.ParseAndCheckProjectsInBackgroundForFile data.FileName)
path "/project" >=> handler (fun (data : ProjectRequest) -> commands.Project data.FileName false ignore)
path "/declarations" >=> handler (fun (data : DeclarationsRequest) -> commands.Declarations data.FileName)
path "/declarationsProjects" >=> fun httpCtx ->
Expand Down Expand Up @@ -151,6 +147,8 @@ let main argv =
path "/symboluse" >=> positionHandler (fun data tyRes lineStr _ -> commands.SymbolUse tyRes { Line = data.Line; Col = data.Column } lineStr)
path "/finddeclaration" >=> positionHandler (fun data tyRes lineStr _ -> commands.FindDeclarations tyRes { Line = data.Line; Col = data.Column } lineStr)
path "/methods" >=> positionHandler (fun data tyRes _ lines -> commands.Methods tyRes { Line = data.Line; Col = data.Column } lines)
path "/help" >=> positionHandler (fun data tyRes line _ -> commands.Help tyRes { Line = data.Line; Col = data.Column } line)

path "/compilerlocation" >=> fun httpCtx ->
async {
let res = commands.CompilerLocation() |> List.toArray |> Json.toJson
Expand Down
10 changes: 0 additions & 10 deletions src/FsAutoComplete.Suave/FsAutoComplete.Suave.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,6 @@
<Private>True</Private>
<Paket>True</Paket>
</Reference>
<Reference Include="FSharp.Compiler.Service.MSBuild.v12">
<HintPath>..\..\packages\FSharp.Compiler.Service\lib\net45\stock\FSharp.Compiler.Service.MSBuild.v12.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
<Reference Include="FSharp.Compiler.Service">
<HintPath>..\..\packages\FSharp.Compiler.Service\lib\net45\stock\FSharp.Compiler.Service.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
Expand Down
29 changes: 28 additions & 1 deletion src/FsAutoComplete.Suave/JsonSerializer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ namespace FsAutoComplete

module JsonSerializer =

open System
open Microsoft.FSharp.Reflection
open Newtonsoft.Json
open Newtonsoft.Json.Converters
open Microsoft.FSharp.Compiler
Expand Down Expand Up @@ -48,10 +50,35 @@ module JsonSerializer =
override x.CanRead = false
override x.CanWrite = true

type OptionConverter() =
inherit JsonConverter()

override x.CanConvert(t) =
t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<option<_>>

override x.WriteJson(writer, value, serializer) =
let value =
if isNull value then null
else
let _,fields = FSharpValue.GetUnionFields(value, value.GetType())
fields.[0]
serializer.Serialize(writer, value)

override x.ReadJson(reader, t, existingValue, serializer) =
let innerType = t.GetGenericArguments().[0]
let innerType =
if innerType.IsValueType then (typedefof<Nullable<_>>).MakeGenericType([|innerType|])
else innerType
let value = serializer.Deserialize(reader, innerType)
let cases = FSharpType.GetUnionCases(t)
if isNull value then FSharpValue.MakeUnion(cases.[0], [||])
else FSharpValue.MakeUnion(cases.[1], [|value|])

let private jsonConverters =
[|
new FSharpErrorSeverityConverter() :> JsonConverter;
new FSharpErrorSeverityConverter() :> JsonConverter
new RangeConverter() :> JsonConverter
new OptionConverter() :> JsonConverter
|]

let internal writeJson(o: obj) = JsonConvert.SerializeObject(o, jsonConverters)
10 changes: 0 additions & 10 deletions src/FsAutoComplete/FsAutoComplete.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -101,16 +101,6 @@
<Private>True</Private>
<Paket>True</Paket>
</Reference>
<Reference Include="FSharp.Compiler.Service.MSBuild.v12">
<HintPath>..\..\packages\FSharp.Compiler.Service\lib\net45\stock\FSharp.Compiler.Service.MSBuild.v12.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
<Reference Include="FSharp.Compiler.Service">
<HintPath>..\..\packages\FSharp.Compiler.Service\lib\net45\stock\FSharp.Compiler.Service.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
Expand Down
Loading

0 comments on commit faf516e

Please sign in to comment.