diff --git a/vsintegration/packages.config b/vsintegration/packages.config index 5b5d870661f..1bba175bb9e 100644 --- a/vsintegration/packages.config +++ b/vsintegration/packages.config @@ -18,6 +18,7 @@ + diff --git a/vsintegration/src/FSharp.Editor/CommonHelpers.fs b/vsintegration/src/FSharp.Editor/CommonHelpers.fs index 914c30f1f4b..446b0fd069e 100644 --- a/vsintegration/src/FSharp.Editor/CommonHelpers.fs +++ b/vsintegration/src/FSharp.Editor/CommonHelpers.fs @@ -318,30 +318,6 @@ module internal Extensions = isPrivate && declaredInTheFile - let glyphMajorToRoslynGlyph = function - | GlyphMajor.Class -> Glyph.ClassPublic - | GlyphMajor.Constant -> Glyph.ConstantPublic - | GlyphMajor.Delegate -> Glyph.DelegatePublic - | GlyphMajor.Enum -> Glyph.EnumPublic - | GlyphMajor.EnumMember -> Glyph.FieldPublic - | GlyphMajor.Event -> Glyph.EventPublic - | GlyphMajor.Exception -> Glyph.ClassPublic - | GlyphMajor.FieldBlue -> Glyph.FieldPublic - | GlyphMajor.Interface -> Glyph.InterfacePublic - | GlyphMajor.Method -> Glyph.MethodPublic - | GlyphMajor.Method2 -> Glyph.MethodPublic - | GlyphMajor.Module -> Glyph.ModulePublic - | GlyphMajor.NameSpace -> Glyph.Namespace - | GlyphMajor.Property -> Glyph.PropertyPublic - | GlyphMajor.Struct -> Glyph.StructurePublic - | GlyphMajor.Typedef -> Glyph.ClassPublic - | GlyphMajor.Type -> Glyph.ClassPublic - | GlyphMajor.Union -> Glyph.EnumPublic - | GlyphMajor.Variable -> Glyph.FieldPublic - | GlyphMajor.ValueType -> Glyph.StructurePublic - | GlyphMajor.Error -> Glyph.Error - | _ -> Glyph.None - type Async<'a> with /// Creates an asynchronous workflow that runs the asynchronous workflow given as an argument at most once. /// When the returned workflow is started for the second time, it reuses the result of the previous execution. @@ -362,3 +338,92 @@ module internal Extensions = let! result = input return f result } + +[] +module internal TypedAstExtensionHelpers = + type FSharpEntity with + member this.TryGetFullName() = + match (try this.TryFullName with _ -> None) with + | Some x -> Some x + | None -> + try Some (String.Join(".", this.AccessPath, this.DisplayName)) + with _ -> None + + type FSharpMemberOrFunctionOrValue with + // FullType may raise exceptions (see https://github.com/fsharp/fsharp/issues/307). + member x.FullTypeSafe = try Some x.FullType with _ -> None + + let (|Public|Internal|Protected|Private|) (a: FSharpAccessibility) = + if a.IsPublic then Public + elif a.IsInternal then Internal + elif a.IsPrivate then Private + else Protected + +module internal Glyph = + let forSymbol (symbol: FSharpSymbol) = + match symbol with + | :? FSharpUnionCase as x -> + match x.Accessibility with + | Public -> Glyph.EnumPublic + | Internal -> Glyph.EnumInternal + | Protected -> Glyph.EnumProtected + | Private -> Glyph.EnumPrivate + | :? FSharpActivePatternCase -> Glyph.EnumPublic + | :? FSharpField as x -> + match x.Accessibility with + | Public -> Glyph.FieldPublic + | Internal -> Glyph.FieldInternal + | Protected -> Glyph.FieldProtected + | Private -> Glyph.FieldPrivate + | :? FSharpParameter -> Glyph.Parameter + | :? FSharpMemberOrFunctionOrValue as x -> + if x.IsExtensionMember then + match x.Accessibility with + | Public -> Glyph.ExtensionMethodPublic + | Internal -> Glyph.ExtensionMethodInternal + | Protected -> Glyph.ExtensionMethodProtected + | Private -> Glyph.ExtensionMethodPrivate + elif x.IsProperty || x.IsPropertyGetterMethod || x.IsPropertySetterMethod then + match x.Accessibility with + | Public -> Glyph.PropertyPublic + | Internal -> Glyph.PropertyInternal + | Protected -> Glyph.PropertyProtected + | Private -> Glyph.PropertyPrivate + elif x.IsEvent then + match x.Accessibility with + | Public -> Glyph.EventPublic + | Internal -> Glyph.EventInternal + | Protected -> Glyph.EventProtected + | Private -> Glyph.EventPrivate + else + match x.Accessibility with + | Public -> Glyph.MethodPublic + | Internal -> Glyph.MethodInternal + | Protected -> Glyph.MethodProtected + | Private -> Glyph.MethodPrivate + | :? FSharpEntity as x -> + if x.IsFSharpModule then + match x.Accessibility with + | Public -> Glyph.ModulePublic + | Internal -> Glyph.ModuleInternal + | Protected -> Glyph.ModuleProtected + | Private -> Glyph.ModulePrivate + elif x.IsEnum || x.IsFSharpUnion then + match x.Accessibility with + | Public -> Glyph.EnumPublic + | Internal -> Glyph.EnumInternal + | Protected -> Glyph.EnumProtected + | Private -> Glyph.EnumPrivate + elif x.IsInterface then + match x.Accessibility with + | Public -> Glyph.InterfacePublic + | Internal -> Glyph.InterfaceInternal + | Protected -> Glyph.InterfaceProtected + | Private -> Glyph.InterfacePrivate + else + match x.Accessibility with + | Public -> Glyph.ClassPublic + | Internal -> Glyph.ClassInternal + | Protected -> Glyph.ClassProtected + | Private -> Glyph.ClassPrivate + | _ -> Glyph.None diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index abb2217ebc2..43e07601ae4 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -127,6 +127,9 @@ $(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Package.LanguageService.$(RoslynVSBinariesVersion).$(RoslynVSPackagesVersion)\lib\Microsoft.VisualStudio.Package.LanguageService.$(RoslynVSBinariesVersion).dll + + $(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Language.Intellisense.$(RoslynVSBinariesVersion).$(RoslynVSPackagesVersion)\lib\Microsoft.VisualStudio.Language.Intellisense.$(RoslynVSBinariesVersion).dll + $(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Language.StandardClassification.$(RoslynVSPackagesVersion)\lib\net45\Microsoft.VisualStudio.Language.StandardClassification.dll diff --git a/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs b/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs index 929d55e2f08..bb18b385a4c 100644 --- a/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs +++ b/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs @@ -33,6 +33,7 @@ open Microsoft.VisualStudio.Text.Tagging open Microsoft.VisualStudio.Text.Formatting open Microsoft.VisualStudio.Shell open Microsoft.VisualStudio.Shell.Interop +open Microsoft.VisualStudio.Language.Intellisense open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.Parser @@ -65,7 +66,8 @@ type internal FSharpQuickInfoProvider _classificationFormatMapService: IClassificationFormatMapService, checkerProvider: FSharpCheckerProvider, projectInfoManager: ProjectInfoManager, - typeMap: Shared.Utilities.ClassificationTypeMap + typeMap: Shared.Utilities.ClassificationTypeMap, + glyphService: IGlyphService ) = let xmlMemberIndexService = serviceProvider.GetService(typeof) :?> IVsXMLMemberIndexService @@ -96,10 +98,14 @@ type internal FSharpQuickInfoProvider match quickParseInfo with | Some (islandColumn, qualifiers, textSpan) -> let! res = checkFileResults.GetToolTipTextAlternate(textLineNumber, islandColumn, textLine.ToString(), qualifiers, FSharpTokenTag.IDENT) - return - match res with - | FSharpToolTipText [] -> None - | _ -> Some(res, textSpan) + match res with + | FSharpToolTipText [] -> return None + | _ -> + let! symbolUse = checkFileResults.GetSymbolUseAtLocation(textLineNumber, islandColumn, textLine.ToString(), qualifiers) + match symbolUse with + | Some symbolUse -> + return Some(res, textSpan, symbolUse.Symbol) + | None -> return None | None -> return None } @@ -118,7 +124,7 @@ type internal FSharpQuickInfoProvider let! textVersion = document.GetTextVersionAsync(cancellationToken) |> Async.AwaitTask let! quickInfoResult = FSharpQuickInfoProvider.ProvideQuickInfo(checkerProvider.Checker, document.Id, sourceText, document.FilePath, position, options, textVersion.GetHashCode(), cancellationToken) match quickInfoResult with - | Some(toolTipElement, textSpan) -> + | Some(toolTipElement, textSpan, symbol) -> let mainDescription = Collections.Generic.List() let documentation = Collections.Generic.List() XmlDocumentation.BuildDataTipText( @@ -130,7 +136,7 @@ type internal FSharpQuickInfoProvider let content = QuickInfoDisplayDeferredContent ( - symbolGlyph = null,//SymbolGlyphDeferredContent(), + symbolGlyph = SymbolGlyphDeferredContent(Glyph.forSymbol symbol, glyphService), warningGlyph = null, mainDescription = ClassifiableDeferredContent(mainDescription, typeMap), documentation = ClassifiableDeferredContent(documentation, typeMap),