提交 7360d04b 编写于 作者: J Jared Hester 提交者: Kevin Ransom (msft)

Quickinfo Tooltip and GotoDefinition Navigation Improvements (#2683)

* full type name in tooltip, provisional tab preferred

* more entities made navigable

* use IGoToDefinition service

* this is used only here

* MEF import FSharpGotoDefinitionService into QuickInfoProvider

* speed up gotoDefinition

* additional GotoDefn navigation strategies

* quickinfo navigation stays in its lane

tooltip from .fsi links to .fsi
tooltip from .fs links to .fs
quick navigation if no redirect is necessary

* fix unittests

* restore recursive matchingDoc

* asynchronous navigation from tooltips

* fix cross project .fs -> .fs and .fsi -> .fsi Navigation

* cleanup and extra documentation

fixed bug in cross project .fs -> .fs navigation

* missed this one

* gotodefinition sig <-> impl at declaration location

* fix async workflow

* animate status bar search and timeout on msgs

* Better links styling

* integrate sig doccoms

* fix error introduced by prior merge

* fixed invalid type access in `getUnusedOpens`

* fix invalid span bug in `symbolIsFullyQualified`

* check if normalized doccom text matches

* cleanup status bar usage

* fix underline pen position, code cleanup and formatting

* do not show links for symbol itself
上级 dd53a3db
......@@ -83,7 +83,10 @@ module internal PrintUtilities =
if isAttribute then
defaultArg (String.tryDropSuffix name "Attribute") name
else name
let tyconTextL = NavigableTaggedText.Create(tagEntityRefName tcref demangled, tcref.DefinitionRange) |> wordL
let tyconTextL =
tagEntityRefName tcref demangled
|> mkNav tcref.DefinitionRange
|> wordL
if denv.shortTypeNames then
tyconTextL
else
......@@ -1104,8 +1107,9 @@ module private PrintTastMemberOrVals =
let stat = PrintTypes.layoutMemberFlags membInfo.MemberFlags
let _tps,argInfos,rty,_ = GetTypeOfMemberInFSharpForm denv.g v
let mkNameL niceMethodTypars tagFunction name =
let nameL = DemangleOperatorNameAsLayout tagFunction name
let mkNameL niceMethodTypars tagFunction name =
let nameL =
DemangleOperatorNameAsLayout (tagFunction >> mkNav v.DefinitionRange) name
let nameL =
if denv.showMemberContainers then
layoutTyconRef denv v.MemberApparentParent ^^ SepL.dot ^^ nameL
......@@ -1157,7 +1161,10 @@ module private PrintTastMemberOrVals =
let env = SimplifyTypes.CollectInfo true [tau] cxs
let cxs = env.postfixConstraints
let argInfos,rty = GetTopTauTypeInFSharpForm denv.g (arityOfVal v).ArgInfos tau v.Range
let nameL = wordL ((if v.IsModuleBinding then tagModuleBinding else tagUnknownEntity) v.DisplayName)
let nameL =
(if v.IsModuleBinding then tagModuleBinding else tagUnknownEntity) v.DisplayName
|> mkNav v.DefinitionRange
|> wordL
let nameL = layoutAccessibility denv v.Accessibility nameL
let nameL =
if v.IsMutable && not denv.suppressMutableKeyword then
......@@ -1389,7 +1396,7 @@ module private TastDefinitionPrinting =
let layoutExtensionMember denv (v:Val) =
let tycon = v.MemberApparentParent.Deref
let nameL = wordL (tagMethod tycon.DisplayName)
let nameL = tagMethod tycon.DisplayName |> mkNav v.DefinitionRange |> wordL
let nameL = layoutAccessibility denv tycon.Accessibility nameL // "type-accessibility"
let tps =
match PartitionValTyparsForApparentEnclosingType denv.g v with
......@@ -1402,7 +1409,10 @@ module private TastDefinitionPrinting =
aboveListL (List.map (layoutExtensionMember denv) vs)
let layoutRecdField addAccess denv (fld:RecdField) =
let lhs = wordL (tagRecordField fld.Name)
let lhs =
tagRecordField fld.Name
|> mkNav fld.DefinitionRange
|> wordL
let lhs = (if addAccess then layoutAccessibility denv fld.Accessibility lhs else lhs)
let lhs = if fld.IsMutable then wordL (tagKeyword "mutable") --- lhs else lhs
(lhs ^^ RightL.colon) --- layoutType denv fld.FormalType
......@@ -1426,7 +1436,7 @@ module private TastDefinitionPrinting =
sepListL (wordL (tagPunctuation "*")) (List.mapi (layoutUnionOrExceptionField denv isGenerated) fields)
let layoutUnionCase denv prefixL (ucase:UnionCase) =
let nmL = DemangleOperatorNameAsLayout tagUnionCase ucase.Id.idText
let nmL = DemangleOperatorNameAsLayout (tagUnionCase >> mkNav ucase.DefinitionRange) ucase.Id.idText
//let nmL = layoutAccessibility denv ucase.Accessibility nmL
match ucase.RecdFields with
| [] -> (prefixL ^^ nmL)
......@@ -1611,6 +1621,7 @@ module private TastDefinitionPrinting =
elif isInterfaceTy g ty then Some "interface", tagInterface n
elif isClassTy g ty then (if simplified then None else Some "class" ), tagClass n
else None, tagUnknownType n
let name = mkNav tycon.DefinitionRange name
let nameL = layoutAccessibility denv tycon.Accessibility (wordL name)
let denv = denv.AddAccessibility tycon.Accessibility
let lhsL =
......
......@@ -2535,11 +2535,16 @@ let tagEntityRefName (xref: EntityRef) name =
elif xref.IsRecordTycon then tagRecord name
else tagClass name
let fullDisplayTextOfTyconRef r = fullNameOfEntityRef (fun (tc:TyconRef) -> tc.DisplayNameWithStaticParametersAndUnderscoreTypars) r
let fullNameOfEntityRefAsLayout nmF (xref: EntityRef) =
let n = NavigableTaggedText.Create(tagEntityRefName xref (nmF xref), xref.DefinitionRange) |> wordL
let navigableText =
tagEntityRefName xref (nmF xref)
|> mkNav xref.DefinitionRange
|> wordL
match fullNameOfParentOfEntityRefAsLayout xref with
| None -> n
| Some pathText -> pathText ^^ SepL.dot ^^ n
| None -> navigableText
| Some pathText -> pathText ^^ SepL.dot ^^ navigableText
let fullNameOfParentOfValRef vref =
match vref with
......@@ -2563,7 +2568,6 @@ let fullNameOfParentOfValRefAsLayout vref =
let fullDisplayTextOfParentOfModRef r = fullNameOfParentOfEntityRef r
let fullDisplayTextOfModRef r = fullNameOfEntityRef (fun (x:EntityRef) -> x.DemangledModuleOrNamespaceName) r
let fullDisplayTextOfTyconRef r = fullNameOfEntityRef (fun (tc:TyconRef) -> tc.DisplayNameWithStaticParametersAndUnderscoreTypars) r
let fullDisplayTextOfTyconRefAsLayout r = fullNameOfEntityRefAsLayout (fun (tc:TyconRef) -> tc.DisplayNameWithStaticParametersAndUnderscoreTypars) r
let fullDisplayTextOfExnRef r = fullNameOfEntityRef (fun (tc:TyconRef) -> tc.DisplayNameWithStaticParametersAndUnderscoreTypars) r
let fullDisplayTextOfExnRefAsLayout r = fullNameOfEntityRefAsLayout (fun (tc:TyconRef) -> tc.DisplayNameWithStaticParametersAndUnderscoreTypars) r
......
......@@ -14,13 +14,12 @@ type layout = Internal.Utilities.StructuredFormat.Layout
type LayoutTag = Internal.Utilities.StructuredFormat.LayoutTag
type TaggedText = Internal.Utilities.StructuredFormat.TaggedText
type NavigableTaggedText(tag, text, range: Range.range) =
type NavigableTaggedText(taggedText: TaggedText, range: Range.range) =
member val Range = range
interface TaggedText with
member x.Tag = tag
member x.Text = text
static member Create(tt: TaggedText, range) =
NavigableTaggedText(tt.Tag, tt.Text, range)
member x.Tag = taggedText.Tag
member x.Text = taggedText.Text
let mkNav r t = NavigableTaggedText(t, r)
let spaces n = new String(' ',n)
......
......@@ -13,10 +13,10 @@ type LayoutTag = Internal.Utilities.StructuredFormat.LayoutTag
type TaggedText = Internal.Utilities.StructuredFormat.TaggedText
type NavigableTaggedText =
new : LayoutTag * string * Range.range -> NavigableTaggedText
new : TaggedText * Range.range -> NavigableTaggedText
member Range: Range.range
static member Create: TaggedText * Range.range -> NavigableTaggedText
interface TaggedText
val mkNav : Range.range -> TaggedText -> NavigableTaggedText
module TaggedTextOps = Internal.Utilities.StructuredFormat.TaggedTextOps
......
......@@ -834,7 +834,7 @@ module internal ItemDescriptionsImpl =
wordL (tagText (FSComp.SR.typeInfoUnionCase())) ^^
NicePrint.layoutTyconRef denv ucinfo.TyconRef ^^
sepL (tagPunctuation ".") ^^
wordL (tagUnionCase (DecompileOpName uc.Id.idText)) ^^
wordL (tagUnionCase (DecompileOpName uc.Id.idText) |> mkNav uc.DefinitionRange) ^^
RightL.colon ^^
(if List.isEmpty recd then emptyL else NicePrint.layoutUnionCases denv recd ^^ WordL.arrow) ^^
NicePrint.layoutTy denv rty
......@@ -845,7 +845,7 @@ module internal ItemDescriptionsImpl =
let items = apinfo.ActiveTags
let layout =
wordL (tagText ((FSComp.SR.typeInfoActivePatternResult()))) ^^
wordL (tagActivePatternResult (List.item idx items)) ^^
wordL (tagActivePatternResult (List.item idx items) |> mkNav apinfo.Range) ^^
RightL.colon ^^
NicePrint.layoutTy denv ty
FSharpStructuredToolTipElement.Single(layout, xml)
......@@ -859,7 +859,7 @@ module internal ItemDescriptionsImpl =
let _, ptau, _cxs = PrettyTypes.PrettifyTypes1 denv.g tau
let layout =
wordL (tagText (FSComp.SR.typeInfoActiveRecognizer())) ^^
wordL (tagActivePatternCase apref.Name) ^^
wordL (tagActivePatternCase apref.Name |> mkNav v.DefinitionRange) ^^
RightL.colon ^^
NicePrint.layoutTy denv ptau ^^
OutputFullName isDecl pubpath_of_vref fullDisplayTextOfValRefAsLayout v
......@@ -879,7 +879,7 @@ module internal ItemDescriptionsImpl =
let layout =
NicePrint.layoutTyconRef denv rfinfo.TyconRef ^^
SepL.dot ^^
wordL (tagRecordField (DecompileOpName rfield.Name)) ^^
wordL (tagRecordField (DecompileOpName rfield.Name) |> mkNav rfield.DefinitionRange) ^^
RightL.colon ^^
NicePrint.layoutTy denv ty ^^
(
......@@ -1001,7 +1001,9 @@ module internal ItemDescriptionsImpl =
let layout =
wordL (tagKeyword kind) ^^
wordL (if definiteNamespace then tagNamespace (fullDisplayTextOfModRef modref) else (tagModule modref.DemangledModuleOrNamespaceName))
(if definiteNamespace then tagNamespace (fullDisplayTextOfModRef modref) else (tagModule modref.DemangledModuleOrNamespaceName)
|> mkNav modref.DefinitionRange
|> wordL)
if not definiteNamespace then
let namesToAdd =
([],modrefs)
......
[<AutoOpen>]
module internal Microsoft.VisualStudio.FSharp.Editor.CodeAnalysisExtensions
open Microsoft.CodeAnalysis
open Microsoft.FSharp.Compiler.Range
type Project with
/// Returns the projectIds of all projects within the same solution that directly reference this project
member this.GetDependentProjectIds () =
this.Solution.GetProjectDependencyGraph().GetProjectsThatDirectlyDependOnThisProject this.Id
/// Returns all projects within the same solution that directly reference this project.
member this.GetDependentProjects () =
this.Solution.GetProjectDependencyGraph().GetProjectsThatDirectlyDependOnThisProject this.Id
|> Seq.map this.Solution.GetProject
/// Returns the ProjectIds of all of the projects that this project directly or transitively depneds on
member this.GetProjectIdsOfAllProjectsThisProjectDependsOn () =
let graph = this.Solution.GetProjectDependencyGraph()
let transitiveDependencies = graph.GetProjectsThatThisProjectTransitivelyDependsOn this.Id
let directDependencies = graph.GetProjectsThatThisProjectDirectlyDependsOn this.Id
Seq.append directDependencies transitiveDependencies
/// The list all of the projects that this project directly or transitively depneds on
member this.GetAllProjectsThisProjectDependsOn () =
this.GetProjectIdsOfAllProjectsThisProjectDependsOn ()
|> Seq.map this.Solution.GetProject
type Solution with
/// Try to get a document inside the solution using the document's name
member self.TryGetDocumentNamed docName =
self.Projects |> Seq.tryPick (fun proj ->
proj.Documents |> Seq.tryFind (fun doc -> doc.Name = docName))
/// Try to find the documentId corresponding to the provided filepath within this solution
member self.TryGetDocumentFromPath filePath =
self.GetDocumentIdsWithFilePath filePath
|> Seq.tryHead |> Option.map (fun docId -> self.GetDocument docId)
/// Try to get a project inside the solution using the project's id
member self.TryGetProject (projId:ProjectId) =
if self.ContainsProject projId then Some (self.GetProject projId) else None
/// Returns the projectIds of all projects within this solution that directly reference the provided project
member self.GetDependentProjects (projectId:ProjectId) =
self.GetProjectDependencyGraph().GetProjectsThatDirectlyDependOnThisProject projectId
|> Seq.map self.GetProject
/// Returns the projectIds of all projects within this solution that directly reference the provided project
member self.GetDependentProjectIds (projectId:ProjectId) =
self.GetProjectDependencyGraph().GetProjectsThatDirectlyDependOnThisProject projectId
/// Returns the ProjectIds of all of the projects that directly or transitively depends on
member self.GetProjectIdsOfAllProjectReferences (projectId:ProjectId) =
let graph = self.GetProjectDependencyGraph()
let transitiveDependencies = graph.GetProjectsThatThisProjectTransitivelyDependsOn projectId
let directDependencies = graph.GetProjectsThatThisProjectDirectlyDependsOn projectId
Seq.append directDependencies transitiveDependencies
/// Returns all of the projects that this project that directly or transitively depends on
member self.GetAllProjectsThisProjectDependsOn (projectId:ProjectId) =
self.GetProjectIdsOfAllProjectReferences projectId
|> Seq.map self.GetProject
/// Try to retrieve the corresponding DocumentId for the range's file in the solution
/// and if a projectId is provided, only try to find the document within that project
/// or a project referenced by that project
member self.TryGetDocumentIdFromFSharpRange (range:range,?projectId:ProjectId) =
let filePath = System.IO.Path.GetFullPathSafe range.FileName
let checkProjectId (docId:DocumentId) =
if projectId.IsSome then docId.ProjectId = projectId.Value else false
//The same file may be present in many projects. We choose one from current or referenced project.
let rec matchingDoc = function
| [] -> None
| (docId:DocumentId)::_ when checkProjectId docId -> Some docId
| docId::tail ->
match projectId with
| Some projectId ->
if self.GetDependentProjectIds docId.ProjectId |> Seq.contains projectId
then Some docId
else matchingDoc tail
| None -> Some docId
self.GetDocumentIdsWithFilePath filePath |> List.ofSeq |> matchingDoc
/// Try to retrieve the corresponding Document for the range's file in the solution
/// and if a projectId is provided, only try to find the document within that project
/// or a project referenced by that project
member self.TryGetDocumentFromFSharpRange (range:range,?projectId:ProjectId) =
match projectId with
| Some projectId -> self.TryGetDocumentIdFromFSharpRange (range, projectId)
| None -> self.TryGetDocumentIdFromFSharpRange range
|> Option.map self.GetDocument
......@@ -9,21 +9,46 @@ open Microsoft.CodeAnalysis.Classification
[<RequireQualifiedAccess>]
module internal FSharpCommonConstants =
[<Literal>]
/// "871D2A70-12A2-4e42-9440-425DD92A4116"
let packageGuidString = "871D2A70-12A2-4e42-9440-425DD92A4116"
[<Literal>]
/// "BC6DD5A5-D4D6-4dab-A00D-A51242DBAF1B"
let languageServiceGuidString = "BC6DD5A5-D4D6-4dab-A00D-A51242DBAF1B"
[<Literal>]
/// "4EB7CCB7-4336-4FFD-B12B-396E9FD079A9"
let editorFactoryGuidString = "4EB7CCB7-4336-4FFD-B12B-396E9FD079A9"
[<Literal>]
/// "9B164E40-C3A2-4363-9BC5-EB4039DEF653"
let svsSettingsPersistenceManagerGuidString = "9B164E40-C3A2-4363-9BC5-EB4039DEF653"
[<Literal>]
/// "F#"
let FSharpLanguageName = "F#"
[<Literal>]
/// "F#"
let FSharpContentTypeName = "F#"
[<Literal>]
/// "F# Signature Help"
let FSharpSignatureHelpContentTypeName = "F# Signature Help"
[<Literal>]
/// "F# Language Service"
let FSharpLanguageServiceCallbackName = "F# Language Service"
[<Literal>]
/// "FSharp"
let FSharpLanguageLongName = "FSharp"
[<RequireQualifiedAccess>]
module internal FSharpProviderConstants =
[<Literal>]
let FSharpLanguageLongName = "FSharp"
\ No newline at end of file
/// "Session Capturing Quick Info Source Provider"
let SessionCapturingProvider = "Session Capturing Quick Info Source Provider"
\ No newline at end of file
......@@ -410,8 +410,12 @@ module internal Extensions =
open Microsoft.VisualStudio.FSharp.Editor.Logging
type System.IServiceProvider with
/// Retrieve a MEF Visual Studio Service of type 'T
member x.GetService<'T>() = x.GetService(typeof<'T>) :?> 'T
member x.GetService<'T, 'S>() = x.GetService(typeof<'S>) :?> 'T
/// Retrieve a SVs MEF Service of type 'S and cast it to type 'T
member x.GetService<'S,'T>() = x.GetService(typeof<'S>) :?> 'T
type Path with
static member GetFullPathSafe path =
......@@ -526,7 +530,7 @@ module internal Extensions =
match declarationLocation with
| Some loc ->
let filePath = Path.GetFullPathSafe loc.FileName
let isScript = String.Equals(Path.GetExtension(filePath), ".fsx", StringComparison.OrdinalIgnoreCase)
let isScript = isScriptFile filePath
if isScript && filePath = currentDocument.FilePath then
Some SymbolDeclarationLocation.CurrentDocument
elif isScript then
......
......@@ -82,13 +82,6 @@ module internal CommonRoslynHelpers =
let CollectTaggedText (list: List<_>) (t:TaggedText) = list.Add(TaggedText(roslynTag t.Tag, t.Text))
let CollectNavigableText (list: List<_>) (t: TaggedText) =
let rangeOpt =
match t with
| :? NavigableTaggedText as n -> Some n.Range
| _ -> None
list.Add(roslynTag t.Tag, t.Text, rangeOpt)
let StartAsyncAsTask cancellationToken computation =
let computation =
async {
......@@ -349,10 +342,3 @@ module internal OpenDeclarationHelper =
else sourceText
sourceText, minPos |> Option.defaultValue 0
[<AutoOpen>]
module internal RoslynExtensions =
type Project with
/// The list of all other projects within the same solution that reference this project.
member this.GetDependentProjects() =
this.Solution.GetProjectDependencyGraph().GetProjectsThatDirectlyDependOnThisProject(this.Id)
|> Seq.map this.Solution.GetProject
\ No newline at end of file
namespace Microsoft.VisualStudio.FSharp.Editor.Logging
open System
open System.Diagnostics
open System.ComponentModel.Composition
open Microsoft.VisualStudio.Shell
open Microsoft.VisualStudio.Shell.Interop
......@@ -70,6 +71,8 @@ type [<Export>] Logger [<ImportingConstructor>]
[<AutoOpen>]
module Logging =
let inline debug msg = Printf.kprintf Debug.WriteLine msg
let private logger = lazy Logger(Logger.GlobalServiceProvider)
let private log logType msg = logger.Value.Log(logType,msg)
......
......@@ -2,11 +2,37 @@
module Microsoft.VisualStudio.FSharp.Editor.Pervasive
open System
open System.IO
open System.Threading
open System.Threading.Tasks
open System.Diagnostics
/// Checks if the filePath ends with ".fsi"
let isSignatureFile (filePath:string) =
Path.GetExtension filePath = ".fsi"
/// Checks if the file paht ends with '.fsx' or '.fsscript'
let isScriptFile (filePath:string) =
let ext = Path.GetExtension filePath
String.Equals (ext,".fsi",StringComparison.OrdinalIgnoreCase) || String.Equals (ext,".fsscript",StringComparison.OrdinalIgnoreCase)
/// Path combination operator
let (</>) path1 path2 = Path.Combine (path1, path2)
type Path with
static member GetFullPathSafe path =
try Path.GetFullPath path
with _ -> path
static member GetFileNameSafe path =
try Path.GetFileName path
with _ -> path
[<RequireQualifiedAccess>]
module String =
open System.IO
let getLines (str: string) =
use reader = new StringReader(str)
......@@ -178,6 +204,8 @@ let inline liftAsync (computation : Async<'T>) : Async<'T option> =
return Some a
}
let liftTaskAsync task = task |> Async.AwaitTask |> liftAsync
module Async =
let map (f: 'T -> 'U) (a: Async<'T>) : Async<'U> =
async {
......@@ -199,6 +227,40 @@ module Async =
}
async { return! agent.PostAndAsyncReply id }
type Async with
/// Better implementation of Async.AwaitTask that correctly passes the exception of a failed task to the async mechanism
static member AwaitTaskCorrect (task:Task) : Async<unit> =
Async.FromContinuations (fun (successCont,exceptionCont,_cancelCont) ->
task.ContinueWith (fun (task:Task) ->
if task.IsFaulted then
let e = task.Exception
if e.InnerExceptions.Count = 1 then
exceptionCont e.InnerExceptions.[0]
else exceptionCont e
elif task.IsCanceled then
exceptionCont(TaskCanceledException ())
else successCont ())
|> ignore)
/// Better implementation of Async.AwaitTask that correctly passes the exception of a failed task to the async mechanism
static member AwaitTaskCorrect (task:'T Task) : Async<'T> =
Async.FromContinuations( fun (successCont,exceptionCont,_cancelCont) ->
task.ContinueWith (fun (task:'T Task) ->
if task.IsFaulted then
let e = task.Exception
if e.InnerExceptions.Count = 1 then
exceptionCont e.InnerExceptions.[0]
else exceptionCont e
elif task.IsCanceled then
exceptionCont (TaskCanceledException ())
else successCont task.Result)
|> ignore)
static member RunTaskSynchronously task =
task |> Async.AwaitTask |> Async.RunSynchronously
type AsyncBuilder with
member __.Bind(computation: System.Threading.Tasks.Task<'a>, binder: 'a -> Async<'b>): Async<'b> =
async {
......
......@@ -71,7 +71,10 @@ module private UnusedOpens =
let symbolIsFullyQualified (sourceText: SourceText) (sym: FSharpSymbolUse) (fullName: string) =
match CommonRoslynHelpers.TryFSharpRangeToTextSpan(sourceText, sym.RangeAlternate) with
| Some span -> sourceText.ToString(span) = fullName
| Some span // check that the symbol hasn't provided an invalid span
when sourceText.Length < span.Start
|| sourceText.Length < span.End -> false
| Some span -> sourceText.ToString span = fullName
| None -> false
let getUnusedOpens (sourceText: SourceText) (parsedInput: ParsedInput) (symbolUses: FSharpSymbolUse[]) =
......@@ -102,7 +105,7 @@ module private UnusedOpens =
Some ([apc.FullName], apc.Group.EnclosingEntity)
| SymbolUse.UnionCase uc when not (isQualified uc.FullName) ->
Some ([uc.FullName], Some uc.ReturnType.TypeDefinition)
| SymbolUse.Parameter p when not (isQualified p.FullName) ->
| SymbolUse.Parameter p when not (isQualified p.FullName) && p.Type.HasTypeDefinition ->
Some ([p.FullName], Some p.Type.TypeDefinition)
| _ -> None
......
......@@ -37,6 +37,7 @@
<Compile Include="Common\Logging.fs" />
<Compile Include="Common\CommonHelpers.fs" />
<Compile Include="Common\CommonRoslynHelpers.fs" />
<Compile Include="Common\CodeAnalysisExtensions.fs" />
<Compile Include="Common\ContentType.fs" />
<Compile Include="Common\LanguageService.fs" />
<Compile Include="Common\SymbolHelpers.fs" />
......@@ -57,13 +58,13 @@
<Compile Include="Completion\FileSystemCompletion.fs" />
<Compile Include="Completion\CompletionService.fs" />
<Compile Include="Completion\SignatureHelp.fs" />
<Compile Include="QuickInfo\QuickInfoProvider.fs" />
<Compile Include="InlineRename\InlineRenameService.fs" />
<Compile Include="DocumentHighlights\DocumentHighlightsService.fs" />
<Compile Include="Navigation\GoToDefinitionService.fs" />
<Compile Include="Navigation\NavigationBarItemService.fs" />
<Compile Include="Navigation\NavigateToSearchService.fs" />
<Compile Include="Navigation\FindUsagesService.fs" />
<Compile Include="QuickInfo\QuickInfoProvider.fs" />
<Compile Include="BlockComment\CommentUncommentService.fs" />
<Compile Include="Structure\Structure.fs" />
<Compile Include="Structure\BlockStructureService.fs" />
......@@ -113,6 +114,7 @@
<Reference Include="System.Drawing" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml" />
<Reference Include="UIAutomationTypes" />
<Reference Include="WindowsBase" />
<Reference Include="System" />
<Reference Include="PresentationCore" />
......
......@@ -101,7 +101,6 @@ let _ = Module1.foo 1
let documentId = DocumentId.CreateNewId(ProjectId.CreateNewId())
let actual =
FSharpGoToDefinitionService.FindDefinition(FSharpChecker.Instance, documentId, SourceText.From(fileContents), filePath, caretPosition, [], options, 0)
|> Async.RunSynchronously
|> Option.map (fun range -> (range.StartLine, range.EndLine, range.StartColumn, range.EndColumn))
if actual <> expected then
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册