Skip to content

Quick info glyph #2028

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
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
1 change: 1 addition & 0 deletions vsintegration/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<package id="Microsoft.VisualStudio.Shell.Design" version="14.3.25407" targetFramework="net46" />
<package id="Microsoft.VisualStudio.Settings.15.0" version="15.0.25824-RC" targetFramework="net46" />
<package id="Microsoft.VisualStudio.Utilities" version="14.3.25407" targetFramework="net46" />
<package id="Microsoft.VisualStudio.Imaging" version="14.3.25407" targetFramework="net46" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or perhaps we should get 2.0.0-rc2 versions published

<package id="Microsoft.VisualStudio.Language.StandardClassification" version="14.3.25407" targetFramework="net46" />
<package id="Microsoft.VisualStudio.Language.Intellisense" version="14.3.25407" targetFramework="net46" />
<package id="Microsoft.VisualStudio.Designer.Interfaces" version="1.1.4322" />
Expand Down
89 changes: 89 additions & 0 deletions vsintegration/src/FSharp.Editor/Common/CommonHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -372,3 +372,92 @@ module internal Extensions =
let! result = input
return f result
}

[<AutoOpen>]
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
11 changes: 9 additions & 2 deletions vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -->
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
Expand All @@ -18,7 +18,8 @@
<TargetType>LIBRARY</TargetType>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<NoWarn>$(NoWarn);75</NoWarn>
<Tailcalls Condition="'$(CodeCoverage)' != ''">false</Tailcalls> <OtherFlags>$(OtherFlags) --warnon:1182 --subsystemversion:6.00</OtherFlags>
<Tailcalls Condition="'$(CodeCoverage)' != ''">false</Tailcalls>
<OtherFlags>$(OtherFlags) --warnon:1182 --subsystemversion:6.00</OtherFlags>
<ImportVSSDKTargets>true</ImportVSSDKTargets>
<CreateVsixContainer>false</CreateVsixContainer>
<DeployExtension>false</DeployExtension>
Expand Down Expand Up @@ -85,6 +86,9 @@
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="PresentationFramework" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
<Reference Include="System" />
<Reference Include="PresentationCore" />
Expand Down Expand Up @@ -115,6 +119,9 @@
<Reference Include="Microsoft.VisualStudio.CoreUtility, Version=$(RoslynVSBinariesVersion).0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>$(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.CoreUtility.$(RoslynVSPackagesVersion)\lib\net45\Microsoft.VisualStudio.CoreUtility.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Imaging, Version=$(RoslynVSBinariesVersion).0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>$(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Imaging.$(RoslynVSPackagesVersion)\lib\net45\Microsoft.VisualStudio.Imaging.dll</HintPath>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The package path might not be right.

</Reference>
<Reference Include="Microsoft.VisualStudio.Utilities, Version=$(RoslynVSBinariesVersion).0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>$(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Utilities.$(RoslynVSPackagesVersion)\lib\net45\Microsoft.VisualStudio.Utilities.dll</HintPath>
</Reference>
Expand Down
66 changes: 57 additions & 9 deletions vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs
Original file line number Diff line number Diff line change
Expand Up @@ -25,36 +25,78 @@ open Microsoft.CodeAnalysis.Formatting
open Microsoft.CodeAnalysis.Host.Mef
open Microsoft.CodeAnalysis.Options
open Microsoft.CodeAnalysis.Text
open Microsoft.CodeAnalysis.Editor.Shared.Extensions

open Microsoft.VisualStudio.Language.Intellisense
open Microsoft.VisualStudio.FSharp.LanguageService
open Microsoft.VisualStudio.Text
open Microsoft.VisualStudio.Text.Classification
open Microsoft.VisualStudio.Text.Tagging
open Microsoft.VisualStudio.Text.Formatting
open Microsoft.VisualStudio.Shell
open Microsoft.VisualStudio.Shell.Interop
open Microsoft.VisualStudio.Imaging
open Microsoft.VisualStudio.Imaging.Interop
open Microsoft.VisualStudio.PlatformUI

open Microsoft.FSharp.Compiler
open Microsoft.FSharp.Compiler.Parser
open Microsoft.FSharp.Compiler.Range
open Microsoft.FSharp.Compiler.SourceCodeServices

open System.Windows.Documents
open System.Windows.Controls
open System.Windows.Data
open System.Windows.Media

// FSROSLYNTODO: with the merge of the below PR, the QuickInfo API should be changed
// to allow for a more flexible syntax for defining the content of the tooltip.
// The below interface should be discarded then or updated accourdingly.
// https://github.com/dotnet/roslyn/pull/13623
type internal FSharpDeferredQuickInfoContent(content: string, textProperties: TextFormattingRunProperties) =
type internal FSharpDeferredQuickInfoContent(content: string, textProperties: TextFormattingRunProperties, glyph: Glyph) =
interface IDeferredQuickInfoContent with
override this.Create() : FrameworkElement =
let moniker = GlyphExtensions.GetImageMoniker(glyph)
let image = new CrispImage()
image.Moniker <- (box moniker) :?> _

// Inform the ImageService of the background color so that images have the correct background.
let binding =
Binding(
"Background",
Converter = new BrushToColorConverter(),
RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof<StackPanel>, 1))

image.SetBinding(ImageThemingUtilities.ImageBackgroundColorProperty, binding) |> ignore

image.Margin <- new Thickness(1., 1., 3., 1.)
let symbolGlyphBorder =
new Border(
BorderThickness = new Thickness(0.),
BorderBrush = Brushes.Transparent,
VerticalAlignment = VerticalAlignment.Top,
Child = image)

let textBlock = TextBlock(Run(content), TextWrapping = TextWrapping.Wrap, TextTrimming = TextTrimming.None)
textBlock.SetValue(TextElement.BackgroundProperty, textProperties.BackgroundBrush)
textBlock.SetValue(TextElement.ForegroundProperty, textProperties.ForegroundBrush)
textBlock.SetValue(TextElement.FontFamilyProperty, textProperties.Typeface.FontFamily)
textBlock.SetValue(TextElement.FontSizeProperty, textProperties.FontRenderingEmSize)
textBlock.SetValue(TextElement.FontStyleProperty, if textProperties.Italic then FontStyles.Italic else FontStyles.Normal)
textBlock.SetValue(TextElement.FontWeightProperty, if textProperties.Bold then FontWeights.Bold else FontWeights.Normal)
upcast textBlock

let symbolGlyphAndMainDescriptionDock =
new DockPanel(
LastChildFill = true,
HorizontalAlignment = HorizontalAlignment.Stretch,
Background = Brushes.Transparent)

symbolGlyphAndMainDescriptionDock.Children.Add(symbolGlyphBorder) |> ignore
symbolGlyphAndMainDescriptionDock.Children.Add(textBlock) |> ignore

let panel = StackPanel(Orientation = Orientation.Vertical)
panel.Children.Add(symbolGlyphAndMainDescriptionDock) |> ignore
upcast panel

[<Shared>]
[<ExportQuickInfoProvider(PredefinedQuickInfoProviderNames.Semantic, FSharpCommonConstants.FSharpLanguageName)>]
Expand All @@ -70,7 +112,8 @@ type internal FSharpQuickInfoProvider
let xmlMemberIndexService = serviceProvider.GetService(typeof<SVsXMLMemberIndexService>) :?> IVsXMLMemberIndexService
let documentationBuilder = XmlDocumentation.CreateDocumentationBuilder(xmlMemberIndexService, serviceProvider.DTE)

static member ProvideQuickInfo(checker: FSharpChecker, documentId: DocumentId, sourceText: SourceText, filePath: string, position: int, options: FSharpProjectOptions, textVersionHash: int, cancellationToken: CancellationToken) =
static member ProvideQuickInfo(checker: FSharpChecker, documentId: DocumentId, sourceText: SourceText, filePath: string, position: int,
options: FSharpProjectOptions, textVersionHash: int, cancellationToken: CancellationToken) =
async {
let! _parseResults, checkResultsAnswer = checker.ParseAndCheckFileInProject(filePath, textVersionHash, sourceText.ToString(), options)
let checkFileResults =
Expand All @@ -84,6 +127,7 @@ type internal FSharpQuickInfoProvider
let textLineColumn = textLinePos.Character
//let qualifyingNames, partialName = QuickParse.GetPartialLongNameEx(textLine.ToString(), textLineColumn - 1)
let defines = CompilerEnvironment.GetCompilationDefinesForEditing(filePath, options.OtherOptions |> Seq.toList)

let tryClassifyAtPosition position =
CommonHelpers.tryClassifyAtPosition(documentId, sourceText, filePath, defines, position, SymbolSearchKind.DoesNotIncludeRightColumn, cancellationToken)

Expand All @@ -95,10 +139,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
}

Expand All @@ -117,10 +165,10 @@ 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 dataTipText = XmlDocumentation.BuildDataTipText(documentationBuilder, toolTipElement)
let textProperties = classificationFormatMapService.GetClassificationFormatMap("tooltip").DefaultTextProperties
return QuickInfoItem(textSpan, FSharpDeferredQuickInfoContent(dataTipText, textProperties))
return QuickInfoItem(textSpan, FSharpDeferredQuickInfoContent(dataTipText, textProperties, Glyph.forSymbol symbol))
| None -> return null
| None -> return null
| None -> return null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@
<Reference Include="Microsoft.VisualStudio.ComponentModelHost, Version=$(RoslynVSBinariesVersion).0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>$(FSharpSourcesRoot)\..\packages\Roslyn.Microsoft.VisualStudio.ComponentModelHost.0.0.2\lib\net46\Microsoft.VisualStudio.ComponentModelHost.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Imaging, Version=$(RoslynVSBinariesVersion).0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>$(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Imaging.$(RoslynVSPackagesVersion)\lib\net45\Microsoft.VisualStudio.Imaging.dll</HintPath>
</Reference>
<ProjectReference Include="$(FSharpSourcesRoot)\fsharp\FSharp.Core\FSharp.Core.fsproj">
<Project>{DED3BBD7-53F4-428A-8C9F-27968E768605}</Project>
<Name>FSharp.Core</Name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@
<Reference Include="Microsoft.VisualStudio.Shell.UI.Internal, Version=$(RoslynVSBinariesVersion).0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>$(FSharpSourcesRoot)\..\packages\Microsoft.VisualFSharp.Microsoft.VisualStudio.Shell.UI.Internal.14.0.25420\lib\net45\Microsoft.VisualStudio.Shell.UI.Internal.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Imaging, Version=$(RoslynVSBinariesVersion).0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>$(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Imaging.$(RoslynVSPackagesVersion)\lib\net45\Microsoft.VisualStudio.Imaging.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<ProjectReference Include="$(FSharpSourcesRoot)\fsharp\FSharp.Core\FSharp.Core.fsproj">
<Project>{DED3BBD7-53F4-428A-8C9F-27968E768605}</Project>
Expand Down
3 changes: 3 additions & 0 deletions vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@
<HintPath>$(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Shell.$(RoslynVSBinariesVersion).$(RoslynVSPackagesVersion)\lib\Microsoft.VisualStudio.Shell.$(RoslynVSBinariesVersion).dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Imaging, Version=$(RoslynVSBinariesVersion).0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>$(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Imaging.$(RoslynVSPackagesVersion)\lib\net45\Microsoft.VisualStudio.Imaging.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<Private>True</Private>
<HintPath>$(NUnitLibDir)\nunit.framework.dll</HintPath>
Expand Down
2 changes: 1 addition & 1 deletion vsintegration/tests/unittests/QuickInfoProviderTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,5 @@ Full name: System.Console"
FSharpQuickInfoProvider.ProvideQuickInfo(FSharpChecker.Instance, documentId, SourceText.From(fileContents), filePath, caretPosition, options, 0, CancellationToken.None)
|> Async.RunSynchronously

let actual = quickInfo |> Option.map (fun (text, _) -> getQuickInfoText text)
let actual = quickInfo |> Option.map (fun (text, _, _) -> getQuickInfoText text)
Assert.AreEqual(expected, actual)
3 changes: 3 additions & 0 deletions vsintegration/tests/unittests/VisualFSharp.Unittests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@
<HintPath>$(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Editor.$(RoslynVSPackagesVersion)\lib\net45\Microsoft.VisualStudio.Editor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Imaging, Version=$(RoslynVSBinariesVersion).0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>$(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Imaging.$(RoslynVSPackagesVersion)\lib\net45\Microsoft.VisualStudio.Imaging.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TextManager.Interop.dll" />
<Reference Include="Microsoft.VisualStudio.TextManager.Interop.8.0.dll" />
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.10.0, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
Expand Down