Skip to content
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

Quickinfo Tooltip and GotoDefinition Navigation Improvements #2683

Merged
merged 29 commits into from
Apr 3, 2017

Conversation

cloudRoutine
Copy link
Contributor

@cloudRoutine cloudRoutine commented Mar 23, 2017

  • more navigable entities
  • faster navigation
  • try not to block on navigation
  • piggyback on gotoDefinition service to setup future gotoMetadata navigation
  • symbols in signatures navigate to other signatures
  • symbols in implementations navigate to other implementation files
  • animate "searching" icon on status bar during execution

addresses parts of #2673

match candidates.Length with
| 0 -> None
| 1 -> Some (self.GetDocument candidates.[0])
| _ ->
Copy link
Contributor

Choose a reason for hiding this comment

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

what about

match candidates with
| [||] -> None
| [|_|] -> ...
| _ -> ...

?

Copy link
Contributor

Choose a reason for hiding this comment

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

let r = candidates |> Seq.tryFind (fun docId ->
(self.GetDependentProjects docId.ProjectId
|> Seq.tryFind (fun proj -> proj.Id = projectId))
|> Option.isSome)
Copy link
Contributor

Choose a reason for hiding this comment

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

Seq.exists?

Path.GetExtension filePath = ".fsi"



Copy link
Contributor

Choose a reason for hiding this comment

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

Why so many empty lines?


static member RunTaskSynchronously task =
task |>
Async.AwaitTask |> Async.RunSynchronously
Copy link
Contributor

Choose a reason for hiding this comment

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

Weird formatting.

/// Parse and check the provided document and try to find the defition of the symbol at the position
let checkAndFindDefinition
(checker: FSharpChecker, documentKey: DocumentId, sourceText: SourceText, filePath: string, position: int,
defines: string list, options: FSharpProjectOptions, textVersionHash: int) : Option<range> = maybe {
Copy link
Contributor

Choose a reason for hiding this comment

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

I understand that we pass so many stuff here in order to make it tastable, because we cannot use Document here. But this bunch of parameters are passed to many functions in FSharp.Editor project. What about a new data type, like this:

type EditorDocument =
  { FilePath: string
    Key: DocumentId
    Text: SourceText
    TextVersionHash: int 
    Defines: string[] }

?

Copy link
Contributor

Choose a reason for hiding this comment

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

(maybe add FSharpOptions into it as well)

let fileName = try System.IO.Path.GetFullPath range.FileName with _ -> range.FileName
let refDocumentIds = document.Project.Solution.GetDocumentIdsWithFilePath fileName
if not refDocumentIds.IsEmpty then
let refDocumentId = refDocumentIds.First()
Copy link
Contributor

Choose a reason for hiding this comment

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

|> Seq.toList ... match ... with | refDocumentId :: _ -> ... | [] -> return None ?

| false, _ , Some range, _ -> return Some range
| false, _ , None , Some range -> return Some range
| false, Some range, None , None -> return Some range
| _ , None , None , None ->
Copy link
Contributor

Choose a reason for hiding this comment

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

This big decision table is hard to understand.


/// find the definition location (implementation file/.fs) of the target symbol
let findDefinitionOfSymbolAtRange
(document:Document, range:range, sourceText:SourceText, checker: FSharpChecker, projectInfoManager: ProjectInfoManager) =
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure type annotations here are worth the noise.




[<Shared>]
Copy link
Contributor

Choose a reason for hiding this comment

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

Shared is by default, you can remove it.

try let navList = List<INavigableItem>()
let! navItem = navFunction args
navList.Add navItem
return navList.AsEnumerable()
Copy link
Contributor

Choose a reason for hiding this comment

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

Returning seq from an async computation looks a bit unsafe. In this case it's ok, but I'd prefer an array or a list.

navigationTask.RunSynchronously ()

if navigationTask.Status = TaskStatus.RanToCompletion && navigationTask.Result.Any() then
let navigableItem = navigationTask.Result.First() // F# API provides only one INavigableItem
Copy link
Contributor

Choose a reason for hiding this comment

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

Seq.toList ... match?

Copy link
Contributor

Choose a reason for hiding this comment

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

I just feel uncomfortable seeing partial functions usage.

ClassificationTags.GetClassificationTypeName
let targetPath = range.FileName
logInfof "origin document - %s \n" initialDoc.FilePath
logInfof "target range to - %s \n %A" range.FileName range
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove logging. It will appear in release configuration as well, which we certainly don't want.

return! gotoDefinitionService.NavigateToSymbolDefinitionAsync (targetDoc, targetSource, range)
// adjust the target from implmentation to signature
| true, false ->
return! gotoDefinitionService.NavigateToSymbolDeclarationAsync (targetDoc, targetSource, range)
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe add a simple DU to make this true-false thing more readable, like:

type FileType = Signature | Implementation

match isSignatureFile initialDoc.FilePath, isSignatureFile targetPath with 
| Signature, Signature
| Implementation, Implementation -> ...
| Implementation, Signature -> ...
| Signature, Implementation -> ...

?


let layoutTagToFormatting =
roslynTag
>> ClassificationTags.GetClassificationTypeName
>> typemap.GetClassificationType
>> formatMap.GetTextProperties
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe use piping instead of composition? It's quite hard to read.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it'd basically look the same with pipes

yield run
//| :? Layout.NavigableTaggedText as nav ->
// run.ToolTip <- nav.FullName
// run :> Documents.Inline
Copy link
Contributor

Choose a reason for hiding this comment

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

Commented code.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ooops, that's mine. @cloudRoutine pulled in rather wip stuff.

module internal FSharpQuickInfo =

[<Literal>]
let SessionCapturingProviderName = "Session Capturing Quick Info Source Provider"
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe let's leave the literal.

let h = Documents.Hyperlink(Documents.Run(text), ToolTip = range.FileName)
h.Click.Add <| fun _ -> goTo range
for taggedText in content do
let run = Documents.Run(taggedText.Text, ToolTip = taggedText.Tag ) :> Documents.Inline
Copy link
Contributor

Choose a reason for hiding this comment

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

Tooltip here was or debug, it shows LayoutTag for element at the moment. We can remove it for now.

@majocha
Copy link
Contributor

majocha commented Mar 28, 2017

f12
Last one, passable I think. I'm getting back to the options integration.

@saul
Copy link
Contributor

saul commented Mar 28, 2017

I'm going to throw a spanner in the works and say I prefer it underlined. I don't think the dotted is readable at all - maybe dashed? Again I think this should be an option.

@saul
Copy link
Contributor

saul commented Mar 28, 2017

Also I'd like to say that I don't think we should be making any changes to the way the "Could not navigate to symbol under caret" dialog. I think the status bar changes should be put into a separate into for discussion.

@cloudRoutine
Copy link
Contributor Author

@majocha i tried what you suggested and I got this error

it seems the problem was getUnusedOpens what trying to get the type from a symbol that didn't have one, after I threw in a guard I stopped getting that error

@cloudRoutine
Copy link
Contributor Author

@majocha it appears that links to internally defined types don't appear in the signatures for externally defined types

but they do appear for the methods

@KevinRansom
Copy link
Member

@majocha, @cloudRoutine

what is the status of this PR?

Thanks

Kevin

@majocha
Copy link
Contributor

majocha commented Mar 31, 2017

@KevinRansom It works great now, but as I understand there's a not settled discussion.

@cartermp
Copy link
Contributor

Agreed with @saul and @vasily-kirichenko about the status bar change. I think that's more of a usability change than a bug fix or feature enhancement.

@vasily-kirichenko
Copy link
Contributor

The light and bold lines are not at the same position:

1

@cloudRoutine
Copy link
Contributor Author

@cartermp it's also keeping consistency with the gotodefinition VFPT feature in vs2015

@vasily-kirichenko
Copy link
Contributor

Fixed

1

@vasily-kirichenko
Copy link
Contributor

I'd prefer to not show link for the symbol itself if we are at it's definition already

image

@majocha
Copy link
Contributor

majocha commented Mar 31, 2017

@vasily-kirichenko misalignment should be fixed, waiting to be merged.

@vasily-kirichenko
Copy link
Contributor

@cloudRoutine pull my branch again, I've fixed showing link for symbol itself.

@cloudRoutine
Copy link
Contributor Author

@KevinRansom this branch is good to merge now

@KevinRansom
Copy link
Member

@clousdroutine

Thanks for this @majocha, @cloudRoutine, @vasily-kirichenko

@KevinRansom KevinRansom merged commit 7360d04 into dotnet:master Apr 3, 2017
@saul
Copy link
Contributor

saul commented Apr 3, 2017

Seems like we're a bit too trigger happy on the merge button here. Why has this been merged with valid review comments outstanding from @majocha, and @cartermp agreeing that we shouldn't be putting messages in the status bar?

@KevinRansom
Copy link
Member

@saul ...

Raise an issue for the status line changes.

nosami pushed a commit to xamarin/visualfsharp that referenced this pull request Jan 26, 2022
…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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants