From 6a5580e83720ad8755656d60cbedc7b5bd31b5ce Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 8 Nov 2017 14:51:54 +0300 Subject: [PATCH 1/5] Allow passing additional symbol info in GetDeclarationListInfo --- fcs/samples/EditorService/Program.fs | 4 +-- src/fsharp/vs/ServiceDeclarationLists.fs | 14 +++++------ src/fsharp/vs/ServiceDeclarationLists.fsi | 18 ++++++------- src/fsharp/vs/service.fs | 23 +++++++++++------ src/fsharp/vs/service.fsi | 2 +- tests/service/EditorTests.fs | 25 +++++++++++++++---- .../Completion/CompletionProvider.fs | 6 +++-- 7 files changed, 59 insertions(+), 33 deletions(-) diff --git a/fcs/samples/EditorService/Program.fs b/fcs/samples/EditorService/Program.fs index 5a2cb624f0c..78928080f3b 100644 --- a/fcs/samples/EditorService/Program.fs +++ b/fcs/samples/EditorService/Program.fs @@ -40,8 +40,8 @@ printfn "%A" tip let partialName = GetPartialLongNameEx(inputLines.[4], 23) // Get declarations (autocomplete) for a location -let decls = - parsed.GetDeclarationListInfo(Some untyped, 5, inputLines.[4], partialName, (fun () -> [])) +let decls = + parsed.GetDeclarationListInfo(Some untyped, 5, inputLines.[4], partialName) |> Async.RunSynchronously for item in decls.Items do diff --git a/src/fsharp/vs/ServiceDeclarationLists.fs b/src/fsharp/vs/ServiceDeclarationLists.fs index a36dc3ce69a..964edb3cec0 100644 --- a/src/fsharp/vs/ServiceDeclarationLists.fs +++ b/src/fsharp/vs/ServiceDeclarationLists.fs @@ -484,8 +484,8 @@ module internal DescriptionListsImpl = /// An intellisense declaration [] -type FSharpDeclarationListItem(name: string, nameInCode: string, fullName: string, glyph: FSharpGlyph, info, accessibility: FSharpAccessibility option, - kind: CompletionItemKind, isOwnMember: bool, priority: int, isResolved: bool, namespaceToOpen: string option) = +type FSharpDeclarationListItem<'T>(name: string, nameInCode: string, fullName: string, glyph: FSharpGlyph, info, additionalInfo: 'T option, + kind: CompletionItemKind, isOwnMember: bool, priority: int, isResolved: bool, namespaceToOpen: string option) = let mutable descriptionTextHolder: FSharpToolTipText<_> option = None let mutable task = null @@ -545,7 +545,7 @@ type FSharpDeclarationListItem(name: string, nameInCode: string, fullName: strin (fun err -> FSharpToolTipText [FSharpStructuredToolTipElement.CompositionError err]) member decl.DescriptionText = decl.StructuredDescriptionText |> Tooltips.ToFSharpToolTipText member __.Glyph = glyph - member __.Accessibility = accessibility + member __.AdditionalInfo = additionalInfo member __.Kind = kind member __.IsOwnMember = isOwnMember member __.MinorPriority = priority @@ -555,7 +555,7 @@ type FSharpDeclarationListItem(name: string, nameInCode: string, fullName: strin /// A table of declarations for Intellisense completion [] -type FSharpDeclarationListInfo(declarations: FSharpDeclarationListItem[], isForType: bool, isError: bool) = +type FSharpDeclarationListInfo<'T>(declarations: FSharpDeclarationListItem<'T>[], isForType: bool, isError: bool) = member __.Items = declarations member __.IsForType = isForType member __.IsError = isError @@ -690,14 +690,14 @@ type FSharpDeclarationListInfo(declarations: FSharpDeclarationListItem[], isForT name, nameInCode, fullName, glyph, Choice1Of2 (items, infoReader, m, denv, reactor, checkAlive), getAccessibility item.Item, item.Kind, item.IsOwnMember, item.MinorPriority, item.Unresolved.IsNone, namespaceToOpen)) - new FSharpDeclarationListInfo(Array.ofList decls, isForType, false) + new FSharpDeclarationListInfo<'T>(Array.ofList decls, isForType, false) static member Error msg = - new FSharpDeclarationListInfo( + new FSharpDeclarationListInfo<'T>( [| FSharpDeclarationListItem("", "", "", FSharpGlyph.Error, Choice2Of2 (FSharpToolTipText [FSharpStructuredToolTipElement.CompositionError msg]), None, CompletionItemKind.Other, false, 0, false, None) |], false, true) - static member Empty = FSharpDeclarationListInfo([| |], false, false) + static member Empty = FSharpDeclarationListInfo<'T>([| |], false, false) diff --git a/src/fsharp/vs/ServiceDeclarationLists.fsi b/src/fsharp/vs/ServiceDeclarationLists.fsi index 1ed6e5d4e11..62a51e6fda9 100644 --- a/src/fsharp/vs/ServiceDeclarationLists.fsi +++ b/src/fsharp/vs/ServiceDeclarationLists.fsi @@ -21,9 +21,9 @@ open Microsoft.FSharp.Compiler.Tastops // // Note: this type holds a weak reference to compiler resources. #if COMPILER_PUBLIC_API -type FSharpDeclarationListItem = +type FSharpDeclarationListItem<'T> = #else -type internal FSharpDeclarationListItem = +type internal FSharpDeclarationListItem<'T> = #endif /// Get the display name for the declaration. member Name : string @@ -46,7 +46,7 @@ type internal FSharpDeclarationListItem = member Glyph : FSharpGlyph - member Accessibility : FSharpAccessibility option + member AdditionalInfo : 'T option member Kind : CompletionItemKind @@ -67,23 +67,23 @@ type internal FSharpDeclarationListItem = // // Note: this type holds a weak reference to compiler resources. #if COMPILER_PUBLIC_API -type FSharpDeclarationListInfo = +type FSharpDeclarationListInfo<'T> = #else -type internal FSharpDeclarationListInfo = +type internal FSharpDeclarationListInfo<'T> = #endif - member Items : FSharpDeclarationListItem[] + member Items : FSharpDeclarationListItem<'T>[] member IsForType : bool member IsError : bool // Implementation details used by other code in the compiler - static member internal Create : infoReader:InfoReader * m:range * denv:DisplayEnv * getAccessibility:(Item -> FSharpAccessibility option) * items:CompletionItem list * reactor:IReactorOperations * currentNamespace:string[] option * isAttributeApplicationContex:bool * checkAlive:(unit -> bool) -> FSharpDeclarationListInfo + static member internal Create : infoReader:InfoReader * m:range * denv:DisplayEnv * getAdditionalInfo:(Item -> 'T option) * items:CompletionItem list * reactor:IReactorOperations * currentNamespace:string[] option * isAttributeApplicationContex:bool * checkAlive:(unit -> bool) -> FSharpDeclarationListInfo<'T> - static member internal Error : message:string -> FSharpDeclarationListInfo + static member internal Error : message:string -> FSharpDeclarationListInfo<'T> - static member Empty : FSharpDeclarationListInfo + static member Empty : FSharpDeclarationListInfo<'T> /// Represents one parameter for one method (or other item) in a group. [] diff --git a/src/fsharp/vs/service.fs b/src/fsharp/vs/service.fs index a49e0cf0cdb..cd2f7e4fd02 100644 --- a/src/fsharp/vs/service.fs +++ b/src/fsharp/vs/service.fs @@ -904,21 +904,27 @@ type TypeCheckInfo scope.IsRelativeNameResolvable(cursorPos, plid, symbol.Item) /// Get the auto-complete items at a location - member __.GetDeclarations (ctok, parseResultsOpt, line, lineStr, partialName, getAllSymbols, hasTextChangedSinceLastTypecheck) = + member __.GetDeclarations (ctok, parseResultsOpt, line, lineStr, partialName, getAllSymbols, getAdditionalInfo, shortTypeNames, hasTextChangedSinceLastTypecheck) = let isInterfaceFile = SourceFileImpl.IsInterfaceFile mainInputFileName ErrorScope.Protect Range.range0 (fun () -> match GetDeclItemsForNamesAtPosition(ctok, parseResultsOpt, Some partialName.QualifyingIdents, Some partialName.PartialIdent, partialName.LastDotPos, line, lineStr, partialName.EndColumn + 1, ResolveTypeNamesToCtors, ResolveOverloads.Yes, getAllSymbols, hasTextChangedSinceLastTypecheck) with | None -> FSharpDeclarationListInfo.Empty - | Some (items, denv, ctx, m) -> + | Some (items, denv, ctx, m) -> + let denv = if shortTypeNames then { denv with shortTypeNames = true } else denv + let displayContext = FSharpDisplayContext(fun _ -> denv) + let getAdditionalInfo item = + try getAdditionalInfo(FSharpSymbol.Create(g, thisCcu, tcImports, item), displayContext) + with _ -> + Trace.TraceInformation(sprintf "FCS: could not get additional info for %A" item) + None let items = if isInterfaceFile then items |> List.filter (fun x -> IsValidSignatureFileItem x.Item) else items - let getAccessibility item = FSharpSymbol.GetAccessibility (FSharpSymbol.Create(g, thisCcu, tcImports, item)) let currentNamespaceOrModule = parseResultsOpt |> Option.bind (fun x -> x.ParseTree) |> Option.map (fun parsedInput -> UntypedParseImpl.GetFullNameOfSmallestModuleOrNamespaceAtPoint(parsedInput, mkPos line 0)) let isAttributeApplication = ctx = Some CompletionContext.AttributeApplication - FSharpDeclarationListInfo.Create(infoReader,m,denv,getAccessibility,items,reactorOps,currentNamespaceOrModule,isAttributeApplication,checkAlive)) + FSharpDeclarationListInfo.Create(infoReader,m,denv,getAdditionalInfo,items,reactorOps,currentNamespaceOrModule,isAttributeApplication,checkAlive)) (fun msg -> Trace.TraceInformation(sprintf "FCS: recovering from error in GetDeclarations: '%s'" msg) FSharpDeclarationListInfo.Error msg) @@ -1891,13 +1897,16 @@ type FSharpCheckFileResults(filename: string, errors: FSharpErrorInfo[], scopeOp member info.Errors = errors member info.HasFullTypeCheckInfo = details.IsSome - + /// Intellisense autocompletions - member info.GetDeclarationListInfo(parseResultsOpt, line, lineStr, partialName, getAllEntities, ?hasTextChangedSinceLastTypecheck, ?userOpName: string) = + member info.GetDeclarationListInfo(parseResultsOpt, line, lineStr, partialName, ?getAllEntities, ?getAdditionalInfo: (FSharpSymbol * FSharpDisplayContext -> 'T option), ?shortTypeNames, ?hasTextChangedSinceLastTypecheck, ?userOpName: string) = let userOpName = defaultArg userOpName "Unknown" + let getAllEntities = defaultArg getAllEntities (fun _ -> []) + let getAdditionalInfo = defaultArg getAdditionalInfo (fun _ -> None) + let shortTypeNames = defaultArg shortTypeNames false let hasTextChangedSinceLastTypecheck = defaultArg hasTextChangedSinceLastTypecheck (fun _ -> false) reactorOp userOpName "GetDeclarations" FSharpDeclarationListInfo.Empty (fun ctok scope -> - scope.GetDeclarations(ctok, parseResultsOpt, line, lineStr, partialName, getAllEntities, hasTextChangedSinceLastTypecheck)) + scope.GetDeclarations(ctok, parseResultsOpt, line, lineStr, partialName, getAllEntities, getAdditionalInfo, shortTypeNames, hasTextChangedSinceLastTypecheck)) member info.GetDeclarationListSymbols(parseResultsOpt, line, lineStr, partialName, ?hasTextChangedSinceLastTypecheck, ?userOpName: string) = let userOpName = defaultArg userOpName "Unknown" diff --git a/src/fsharp/vs/service.fsi b/src/fsharp/vs/service.fsi index 1e7005bff08..2509634393f 100755 --- a/src/fsharp/vs/service.fsi +++ b/src/fsharp/vs/service.fsi @@ -148,7 +148,7 @@ type internal FSharpCheckFileResults = /// and assume that we're going to repeat the operation later on. /// /// An optional string used for tracing compiler operations associated with this request. - member GetDeclarationListInfo : ParsedFileResultsOpt:FSharpParseFileResults option * line: int * lineText:string * partialName: PartialLongName * getAllSymbols: (unit -> AssemblySymbol list) * ?hasTextChangedSinceLastTypecheck: (obj * range -> bool) * ?userOpName: string -> Async + member GetDeclarationListInfo : ParsedFileResultsOpt:FSharpParseFileResults option * line: int * lineText:string * partialName: PartialLongName * ?getAllSymbols: (unit -> AssemblySymbol list) * ?getAdditionalInfo: (FSharpSymbol * FSharpDisplayContext -> 'T option) * ?shortTypeNames: bool * ?hasTextChangedSinceLastTypecheck: (obj * range -> bool) * ?userOpName: string -> Async> /// Get the items for a declaration list in FSharpSymbol format /// diff --git a/tests/service/EditorTests.fs b/tests/service/EditorTests.fs index 2e050abe327..a320c62dbb2 100644 --- a/tests/service/EditorTests.fs +++ b/tests/service/EditorTests.fs @@ -87,7 +87,10 @@ let ``Intro test`` () = // (sprintf "%A" tip).Replace("\n","") |> shouldEqual """FSharpToolTipText [Single ("val foo : unit -> unitFull name: Test.foo",None)]""" // Get declarations (autocomplete) for a location let partialName = { QualifyingIdents = []; PartialIdent = "msg"; EndColumn = 22; LastDotPos = None } - let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 7, inputLines.[6], partialName, (fun _ -> []), fun _ -> false)|> Async.RunSynchronously + let decls = + typeCheckResults.GetDeclarationListInfo(Some parseResult, 7, inputLines.[6], partialName, + hasTextChangedSinceLastTypecheck = (fun _ -> false)) + |> Async.RunSynchronously CollectionAssert.AreEquivalent(stringMethods,[ for item in decls.Items -> item.Name ]) // Get overloads of the String.Concat method let methods = typeCheckResults.GetMethods(5, 27, inputLines.[4], Some ["String"; "Concat"]) |> Async.RunSynchronously @@ -286,7 +289,10 @@ let ``Expression typing test`` () = // gives the results for the string type. // for col in 42..43 do - let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 2, inputLines.[1], PartialLongName.Empty(col), (fun _ -> []), fun _ -> false)|> Async.RunSynchronously + let decls = + typeCheckResults.GetDeclarationListInfo(Some parseResult, 2, inputLines.[1], PartialLongName.Empty(col), + hasTextChangedSinceLastTypecheck = (fun _ -> false)) + |> Async.RunSynchronously let autoCompleteSet = set [ for item in decls.Items -> item.Name ] autoCompleteSet |> shouldEqual (set stringMethods) @@ -307,7 +313,10 @@ type Test() = let file = "/home/user/Test.fsx" let parseResult, typeCheckResults = parseAndCheckScript(file, input) - let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 4, inputLines.[3], PartialLongName.Empty(20), (fun _ -> []), fun _ -> false)|> Async.RunSynchronously + let decls = + typeCheckResults.GetDeclarationListInfo(Some parseResult, 4, inputLines.[3], PartialLongName.Empty(20), + hasTextChangedSinceLastTypecheck = (fun _ -> false)) + |> Async.RunSynchronously let item = decls.Items |> Array.tryFind (fun d -> d.Name = "abc") decls.Items |> Seq.exists (fun d -> d.Name = "abc") |> shouldEqual true @@ -324,7 +333,10 @@ type Test() = let file = "/home/user/Test.fsx" let parseResult, typeCheckResults = parseAndCheckScript(file, input) - let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 4, inputLines.[3], PartialLongName.Empty(21), (fun _ -> []), fun _ -> false)|> Async.RunSynchronously + let decls = + typeCheckResults.GetDeclarationListInfo(Some parseResult, 4, inputLines.[3], PartialLongName.Empty(21), + hasTextChangedSinceLastTypecheck = (fun _ -> false)) + |> Async.RunSynchronously let item = decls.Items |> Array.tryFind (fun d -> d.Name = "abc") decls.Items |> Seq.exists (fun d -> d.Name = "abc") |> shouldEqual true @@ -341,7 +353,10 @@ type Test() = let file = "/home/user/Test.fsx" let parseResult, typeCheckResults = parseAndCheckScript(file, input) - let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 4, inputLines.[3], PartialLongName.Empty(14), (fun _ -> []), fun _ -> false)|> Async.RunSynchronously + let decls = + typeCheckResults.GetDeclarationListInfo(Some parseResult, 4, inputLines.[3], PartialLongName.Empty(14), + hasTextChangedSinceLastTypecheck = (fun _ -> false)) + |> Async.RunSynchronously decls.Items |> Seq.exists (fun d -> d.Name = "abc") |> shouldEqual true [] diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs index 7825ccc1bda..949dd3d8155 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs @@ -111,13 +111,15 @@ type internal FSharpCompletionProvider let fcsCaretLineNumber = Line.fromZ caretLinePos.Line // Roslyn line numbers are zero-based, FSharp.Compiler.Service line numbers are 1-based let caretLineColumn = caretLinePos.Character let partialName = QuickParse.GetPartialLongNameEx(caretLine.ToString(), caretLineColumn - 1) - + let getAllSymbols() = getAllSymbols() |> List.filter (fun entity -> entity.FullName.Contains "." && not (PrettyNaming.IsOperatorName entity.Symbol.DisplayName)) + let getAdditionalInfo = fun (symbol, _) -> FSharpSymbol.GetAccessibility symbol + let! declarations = checkFileResults.GetDeclarationListInfo(Some(parseResults), fcsCaretLineNumber, caretLine.ToString(), - partialName, getAllSymbols, userOpName=userOpName) |> liftAsync + partialName, getAllSymbols, getAdditionalInfo, userOpName=userOpName) |> liftAsync let results = List() let getKindPriority = function From cfbe8703e8eb0dedc31ec374f29e1abea2318155 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 8 Nov 2017 15:57:03 +0300 Subject: [PATCH 2/5] FSharp.Editor, FSharp.LanguageService fixes --- .../src/FSharp.Editor/Completion/CompletionProvider.fs | 4 ++-- vsintegration/src/FSharp.LanguageService/Intellisense.fs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs index 949dd3d8155..ec42b67fbcf 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs @@ -34,7 +34,7 @@ type internal FSharpCompletionProvider inherit CompletionProvider() static let userOpName = "CompletionProvider" - static let declarationItemsCache = ConditionalWeakTable() + static let declarationItemsCache = ConditionalWeakTable>() static let [] NameInCodePropName = "NameInCode" static let [] FullNamePropName = "FullName" static let [] IsExtensionMemberPropName = "IsExtensionMember" @@ -147,7 +147,7 @@ type internal FSharpCompletionProvider let maxHints = if mruItems.Values.Count = 0 then 0 else Seq.max mruItems.Values sortedDeclItems |> Array.iteri (fun number declItem -> - let glyph = Tokenizer.FSharpGlyphToRoslynGlyph (declItem.Glyph, declItem.Accessibility) + let glyph = Tokenizer.FSharpGlyphToRoslynGlyph (declItem.Glyph, declItem.AdditionalInfo) let name = match declItem.NamespaceToOpen with | Some namespaceToOpen -> sprintf "%s (open %s)" declItem.Name namespaceToOpen diff --git a/vsintegration/src/FSharp.LanguageService/Intellisense.fs b/vsintegration/src/FSharp.LanguageService/Intellisense.fs index 2a5fa9e6ebf..5338bda9b8d 100644 --- a/vsintegration/src/FSharp.LanguageService/Intellisense.fs +++ b/vsintegration/src/FSharp.LanguageService/Intellisense.fs @@ -116,7 +116,7 @@ type internal ObsoleteGlyph = // functionality and thus have considerable value, they should ony be deleted if we are sure this // is not the case. // -type internal FSharpDeclarations_DEPRECATED(documentationBuilder, declarations: FSharpDeclarationListItem[], reason: BackgroundRequestReason) = +type internal FSharpDeclarations_DEPRECATED(documentationBuilder, declarations: FSharpDeclarationListItem<_>[], reason: BackgroundRequestReason) = inherit Declarations_DEPRECATED() @@ -125,7 +125,7 @@ type internal FSharpDeclarations_DEPRECATED(documentationBuilder, declarations: let mutable lastBestMatch = "" let isEmpty = (declarations.Length = 0) - let tab = Dictionary() + let tab = Dictionary[]>() // Given a prefix, narrow the items to the include the ones containing that prefix, and store in a lookaside table // attached to this declaration set. @@ -535,7 +535,7 @@ type internal FSharpIntellisenseInfo_DEPRECATED let oldTextSnapshot = oldTextSnapshotInfo :?> ITextSnapshot hasTextChangedSinceLastTypecheck (textSnapshot, oldTextSnapshot, Range.Range.toZ range) - let! decls = typedResults.GetDeclarationListInfo(untypedParseInfoOpt, Range.Line.fromZ line, lineText, pname, (fun() -> []), detectTextChange) + let! decls = typedResults.GetDeclarationListInfo(untypedParseInfoOpt, Range.Line.fromZ line, lineText, pname, hasTextChangedSinceLastTypecheck = detectTextChange) return (new FSharpDeclarations_DEPRECATED(documentationBuilder, decls.Items, reason) :> Declarations_DEPRECATED) else // no TypeCheckInfo in ParseResult. From 0dcf2d51c927eb82ee9db1270bbbd2ded33aa632 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 8 Nov 2017 18:18:15 +0300 Subject: [PATCH 3/5] Update xmlDoc for new parameters --- src/fsharp/vs/service.fsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/fsharp/vs/service.fsi b/src/fsharp/vs/service.fsi index 2509634393f..10284be9303 100755 --- a/src/fsharp/vs/service.fsi +++ b/src/fsharp/vs/service.fsi @@ -142,6 +142,14 @@ type internal FSharpCheckFileResults = /// /// Function that returns all symbols from current and referenced assemblies. /// + /// + /// + /// Function that returns additional info about a symbol in completion context. + /// + /// + /// + /// Hide non-opened namespaces in type names in item descriptions and additional info. + /// /// /// If text has been used from a captured name resolution from the typecheck, then /// callback to the client to check if the text has changed. If it has, then give up From 7cb7cee5dffafdf17b9a839eb50267668012135d Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 8 Nov 2017 20:54:38 +0300 Subject: [PATCH 4/5] Trace exception in getAdditionalInfo --- src/fsharp/vs/service.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fsharp/vs/service.fs b/src/fsharp/vs/service.fs index cd2f7e4fd02..94881262813 100644 --- a/src/fsharp/vs/service.fs +++ b/src/fsharp/vs/service.fs @@ -915,8 +915,8 @@ type TypeCheckInfo let displayContext = FSharpDisplayContext(fun _ -> denv) let getAdditionalInfo item = try getAdditionalInfo(FSharpSymbol.Create(g, thisCcu, tcImports, item), displayContext) - with _ -> - Trace.TraceInformation(sprintf "FCS: could not get additional info for %A" item) + with e -> + Trace.TraceInformation(sprintf "FCS: could not get additional info for %A: %O" item e) None let items = if isInterfaceFile then items |> List.filter (fun x -> IsValidSignatureFileItem x.Item) else items let currentNamespaceOrModule = From 467535bb0833a991666942d8610ab759261f4e3b Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Thu, 9 Nov 2017 19:58:58 +0300 Subject: [PATCH 5/5] tmp --- fcs/samples/EditorService/Program.fs | 7 +++-- src/fsharp/vs/ServiceDeclarationLists.fs | 34 +++++++++-------------- src/fsharp/vs/ServiceDeclarationLists.fsi | 31 ++++++++------------- src/fsharp/vs/service.fs | 31 ++++++++++++--------- src/fsharp/vs/service.fsi | 4 ++- 5 files changed, 49 insertions(+), 58 deletions(-) diff --git a/fcs/samples/EditorService/Program.fs b/fcs/samples/EditorService/Program.fs index 78928080f3b..c7d7d7de6a7 100644 --- a/fcs/samples/EditorService/Program.fs +++ b/fcs/samples/EditorService/Program.fs @@ -41,8 +41,9 @@ let partialName = GetPartialLongNameEx(inputLines.[4], 23) // Get declarations (autocomplete) for a location let decls = - parsed.GetDeclarationListInfo(Some untyped, 5, inputLines.[4], partialName) + parsed.GetDeclarationListInfo(Some untyped, 5, inputLines.[4], partialName) |> Async.RunSynchronously -for item in decls.Items do - printfn " - %s" item.Name +match decls with +| FSharpDeclarationListInfo.Info (items, _, _) -> items |> Array.iter (fun item -> printfn " - %s" item.Name) +| _ -> () \ No newline at end of file diff --git a/src/fsharp/vs/ServiceDeclarationLists.fs b/src/fsharp/vs/ServiceDeclarationLists.fs index 964edb3cec0..2033eefa283 100644 --- a/src/fsharp/vs/ServiceDeclarationLists.fs +++ b/src/fsharp/vs/ServiceDeclarationLists.fs @@ -484,8 +484,8 @@ module internal DescriptionListsImpl = /// An intellisense declaration [] -type FSharpDeclarationListItem<'T>(name: string, nameInCode: string, fullName: string, glyph: FSharpGlyph, info, additionalInfo: 'T option, - kind: CompletionItemKind, isOwnMember: bool, priority: int, isResolved: bool, namespaceToOpen: string option) = +type FSharpDeclarationListItem(name: string, nameInCode: string, fullName: string, glyph: FSharpGlyph, info, symbol: FSharpSymbol, + kind: CompletionItemKind, isOwnMember: bool, priority: int, isResolved: bool, namespaceToOpen: string option) = let mutable descriptionTextHolder: FSharpToolTipText<_> option = None let mutable task = null @@ -544,8 +544,8 @@ type FSharpDeclarationListItem<'T>(name: string, nameInCode: string, fullName: s ) (fun err -> FSharpToolTipText [FSharpStructuredToolTipElement.CompositionError err]) member decl.DescriptionText = decl.StructuredDescriptionText |> Tooltips.ToFSharpToolTipText - member __.Glyph = glyph - member __.AdditionalInfo = additionalInfo + member __.Glyph = glyph + member __.Symbol = symbol member __.Kind = kind member __.IsOwnMember = isOwnMember member __.MinorPriority = priority @@ -554,18 +554,18 @@ type FSharpDeclarationListItem<'T>(name: string, nameInCode: string, fullName: s member __.NamespaceToOpen = namespaceToOpen /// A table of declarations for Intellisense completion -[] -type FSharpDeclarationListInfo<'T>(declarations: FSharpDeclarationListItem<'T>[], isForType: bool, isError: bool) = - member __.Items = declarations - member __.IsForType = isForType - member __.IsError = isError +type FSharpDeclarationListInfo = + | Empty + | Info of Items: FSharpDeclarationListItem[] * IsForType: bool * DisplayContext: FSharpDisplayContext + | Error of FSharpToolTipText // Make a 'Declarations' object for a set of selected items - static member Create(infoReader:InfoReader, m, denv, getAccessibility, items: CompletionItem list, reactor, currentNamespaceOrModule: string[] option, isAttributeApplicationContext: bool, checkAlive) = + static member Create(infoReader:InfoReader, m, denv, createSymbol: (Item -> FSharpSymbol), items: CompletionItem list, reactor, currentNamespaceOrModule: string[] option, isAttributeApplicationContext: bool, checkAlive) = let g = infoReader.g let isForType = items |> List.exists (fun x -> x.Type.IsSome) let items = items |> SymbolHelpers.RemoveExplicitlySuppressedCompletionItems g - + let displayContext = FSharpDisplayContext(fun _ -> denv) + let tyconRefOptEq tref1 tref2 = match tref1 with | Some tref1 -> tyconRefEq g tref1 tref2 @@ -687,18 +687,10 @@ type FSharpDeclarationListInfo<'T>(declarations: FSharpDeclarationListItem<'T>[] | ns -> Some (ns |> String.concat ".")) FSharpDeclarationListItem( - name, nameInCode, fullName, glyph, Choice1Of2 (items, infoReader, m, denv, reactor, checkAlive), getAccessibility item.Item, + name, nameInCode, fullName, glyph, Choice1Of2 (items, infoReader, m, denv, reactor, checkAlive), createSymbol item.Item, item.Kind, item.IsOwnMember, item.MinorPriority, item.Unresolved.IsNone, namespaceToOpen)) - new FSharpDeclarationListInfo<'T>(Array.ofList decls, isForType, false) - - static member Error msg = - new FSharpDeclarationListInfo<'T>( - [| FSharpDeclarationListItem("", "", "", FSharpGlyph.Error, Choice2Of2 (FSharpToolTipText [FSharpStructuredToolTipElement.CompositionError msg]), - None, CompletionItemKind.Other, false, 0, false, None) |], false, true) - - static member Empty = FSharpDeclarationListInfo<'T>([| |], false, false) - + FSharpDeclarationListInfo.Info(Array.ofList decls, isForType, displayContext) /// Represents one method (or other item) in a method group. The item may represent either a method or diff --git a/src/fsharp/vs/ServiceDeclarationLists.fsi b/src/fsharp/vs/ServiceDeclarationLists.fsi index 62a51e6fda9..599416c023f 100644 --- a/src/fsharp/vs/ServiceDeclarationLists.fsi +++ b/src/fsharp/vs/ServiceDeclarationLists.fsi @@ -21,9 +21,9 @@ open Microsoft.FSharp.Compiler.Tastops // // Note: this type holds a weak reference to compiler resources. #if COMPILER_PUBLIC_API -type FSharpDeclarationListItem<'T> = +type FSharpDeclarationListItem = #else -type internal FSharpDeclarationListItem<'T> = +type internal FSharpDeclarationListItem = #endif /// Get the display name for the declaration. member Name : string @@ -46,7 +46,7 @@ type internal FSharpDeclarationListItem<'T> = member Glyph : FSharpGlyph - member AdditionalInfo : 'T option + member Symbol : FSharpSymbol member Kind : CompletionItemKind @@ -60,30 +60,21 @@ type internal FSharpDeclarationListItem<'T> = member NamespaceToOpen : string option - -[] +[] /// Represents a set of declarations in F# source code, with information attached ready for display by an editor. /// Returned by GetDeclarations. // // Note: this type holds a weak reference to compiler resources. #if COMPILER_PUBLIC_API -type FSharpDeclarationListInfo<'T> = +type FSharpDeclarationListInfo = #else -type internal FSharpDeclarationListInfo<'T> = +type internal FSharpDeclarationListInfo = #endif - - member Items : FSharpDeclarationListItem<'T>[] - - member IsForType : bool - - member IsError : bool - - // Implementation details used by other code in the compiler - static member internal Create : infoReader:InfoReader * m:range * denv:DisplayEnv * getAdditionalInfo:(Item -> 'T option) * items:CompletionItem list * reactor:IReactorOperations * currentNamespace:string[] option * isAttributeApplicationContex:bool * checkAlive:(unit -> bool) -> FSharpDeclarationListInfo<'T> - - static member internal Error : message:string -> FSharpDeclarationListInfo<'T> - - static member Empty : FSharpDeclarationListInfo<'T> + | Empty + | Info of Items: FSharpDeclarationListItem[] * IsForType: bool * DisplayContext: FSharpDisplayContext + | Error of FSharpToolTipText + // Implementation details used by other code in the compiler + static member internal Create: infoReader:InfoReader * m:range * denv:DisplayEnv * createSymbol: (Item -> FSharpSymbol) * items:CompletionItem list * reactor:IReactorOperations * currentNamespace:string[] option * isAttributeApplicationContex:bool * checkAlive:(unit -> bool) -> FSharpDeclarationListInfo /// Represents one parameter for one method (or other item) in a group. [] diff --git a/src/fsharp/vs/service.fs b/src/fsharp/vs/service.fs index 94881262813..54a80f299d9 100644 --- a/src/fsharp/vs/service.fs +++ b/src/fsharp/vs/service.fs @@ -904,7 +904,7 @@ type TypeCheckInfo scope.IsRelativeNameResolvable(cursorPos, plid, symbol.Item) /// Get the auto-complete items at a location - member __.GetDeclarations (ctok, parseResultsOpt, line, lineStr, partialName, getAllSymbols, getAdditionalInfo, shortTypeNames, hasTextChangedSinceLastTypecheck) = + member __.GetDeclarations (ctok, parseResultsOpt, line, lineStr, partialName, getAllSymbols, shortTypeNames, hasTextChangedSinceLastTypecheck) = let isInterfaceFile = SourceFileImpl.IsInterfaceFile mainInputFileName ErrorScope.Protect Range.range0 (fun () -> @@ -912,22 +912,17 @@ type TypeCheckInfo | None -> FSharpDeclarationListInfo.Empty | Some (items, denv, ctx, m) -> let denv = if shortTypeNames then { denv with shortTypeNames = true } else denv - let displayContext = FSharpDisplayContext(fun _ -> denv) - let getAdditionalInfo item = - try getAdditionalInfo(FSharpSymbol.Create(g, thisCcu, tcImports, item), displayContext) - with e -> - Trace.TraceInformation(sprintf "FCS: could not get additional info for %A: %O" item e) - None + let createSymbol item = FSharpSymbol.Create(g, thisCcu, tcImports, item) let items = if isInterfaceFile then items |> List.filter (fun x -> IsValidSignatureFileItem x.Item) else items let currentNamespaceOrModule = parseResultsOpt |> Option.bind (fun x -> x.ParseTree) |> Option.map (fun parsedInput -> UntypedParseImpl.GetFullNameOfSmallestModuleOrNamespaceAtPoint(parsedInput, mkPos line 0)) let isAttributeApplication = ctx = Some CompletionContext.AttributeApplication - FSharpDeclarationListInfo.Create(infoReader,m,denv,getAdditionalInfo,items,reactorOps,currentNamespaceOrModule,isAttributeApplication,checkAlive)) + FSharpDeclarationListInfo.Create(infoReader,m,denv,createSymbol,items,reactorOps,currentNamespaceOrModule,isAttributeApplication,checkAlive)) (fun msg -> Trace.TraceInformation(sprintf "FCS: recovering from error in GetDeclarations: '%s'" msg) - FSharpDeclarationListInfo.Error msg) + FSharpDeclarationListInfo.Error(FSharpToolTipText [FSharpStructuredToolTipElement.CompositionError msg])) /// Get the symbols for auto-complete items at a location member __.GetDeclarationListSymbols (ctok, parseResultsOpt, line, lineStr, partialName, hasTextChangedSinceLastTypecheck) = @@ -1238,6 +1233,11 @@ type TypeCheckInfo member __.GetFormatSpecifierLocationsAndArity() = sSymbolUses.GetFormatSpecifierLocationsAndArity() + member __.GetAllResolvedSymbols() = + sResolutions.CapturedNameResolutions + |> Seq.map (fun (cnr: CapturedNameResolution) -> cnr.Range, FSharpSymbol.Create(g, thisCcu, tcImports, cnr.Item)) + |> Array.ofSeq + member __.GetSemanticClassification(range: range option) : (range * SemanticClassificationType) [] = ErrorScope.Protect Range.range0 (fun () -> @@ -1899,14 +1899,13 @@ type FSharpCheckFileResults(filename: string, errors: FSharpErrorInfo[], scopeOp member info.HasFullTypeCheckInfo = details.IsSome /// Intellisense autocompletions - member info.GetDeclarationListInfo(parseResultsOpt, line, lineStr, partialName, ?getAllEntities, ?getAdditionalInfo: (FSharpSymbol * FSharpDisplayContext -> 'T option), ?shortTypeNames, ?hasTextChangedSinceLastTypecheck, ?userOpName: string) = + member info.GetDeclarationListInfo(parseResultsOpt, line, lineStr, partialName, ?getAllEntities, ?shortTypeNames, ?hasTextChangedSinceLastTypecheck, ?userOpName: string) = let userOpName = defaultArg userOpName "Unknown" let getAllEntities = defaultArg getAllEntities (fun _ -> []) - let getAdditionalInfo = defaultArg getAdditionalInfo (fun _ -> None) let shortTypeNames = defaultArg shortTypeNames false let hasTextChangedSinceLastTypecheck = defaultArg hasTextChangedSinceLastTypecheck (fun _ -> false) - reactorOp userOpName "GetDeclarations" FSharpDeclarationListInfo.Empty (fun ctok scope -> - scope.GetDeclarations(ctok, parseResultsOpt, line, lineStr, partialName, getAllEntities, getAdditionalInfo, shortTypeNames, hasTextChangedSinceLastTypecheck)) + reactorOp userOpName "GetDeclarations" FSharpDeclarationListInfo.Empty (fun ctok scope -> + scope.GetDeclarations(ctok, parseResultsOpt, line, lineStr, partialName, getAllEntities, shortTypeNames, hasTextChangedSinceLastTypecheck)) member info.GetDeclarationListSymbols(parseResultsOpt, line, lineStr, partialName, ?hasTextChangedSinceLastTypecheck, ?userOpName: string) = let userOpName = defaultArg userOpName "Unknown" @@ -2009,6 +2008,12 @@ type FSharpCheckFileResults(filename: string, errors: FSharpErrorInfo[], scopeOp yield FSharpSymbolUse(scope.TcGlobals, denv, symbol, itemOcc, m) |]) |> async.Return + member info.GetAllResolvedSymbols() = + threadSafeOp + (fun () -> [| |]) + (fun scope -> scope.GetAllResolvedSymbols()) + |> async.Return + member info.GetUsesOfSymbolInFile(symbol:FSharpSymbol) = threadSafeOp (fun () -> [| |]) diff --git a/src/fsharp/vs/service.fsi b/src/fsharp/vs/service.fsi index 10284be9303..98306d3efda 100755 --- a/src/fsharp/vs/service.fsi +++ b/src/fsharp/vs/service.fsi @@ -156,7 +156,7 @@ type internal FSharpCheckFileResults = /// and assume that we're going to repeat the operation later on. /// /// An optional string used for tracing compiler operations associated with this request. - member GetDeclarationListInfo : ParsedFileResultsOpt:FSharpParseFileResults option * line: int * lineText:string * partialName: PartialLongName * ?getAllSymbols: (unit -> AssemblySymbol list) * ?getAdditionalInfo: (FSharpSymbol * FSharpDisplayContext -> 'T option) * ?shortTypeNames: bool * ?hasTextChangedSinceLastTypecheck: (obj * range -> bool) * ?userOpName: string -> Async> + member GetDeclarationListInfo : ParsedFileResultsOpt:FSharpParseFileResults option * line: int * lineText:string * partialName: PartialLongName * ?getAllSymbols: (unit -> AssemblySymbol list) * ?shortTypeNames: bool * ?hasTextChangedSinceLastTypecheck: (obj * range -> bool) * ?userOpName: string -> Async /// Get the items for a declaration list in FSharpSymbol format /// @@ -265,6 +265,8 @@ type internal FSharpCheckFileResults = /// Get all textual usages of all symbols throughout the file member GetAllUsesOfAllSymbolsInFile : unit -> Async + member GetAllResolvedSymbols: unit -> Async<(range * FSharpSymbol)[]> + /// Get the textual usages that resolved to the given symbol throughout the file member GetUsesOfSymbolInFile : symbol:FSharpSymbol -> Async