Skip to content
Open
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 docs/release-notes/.VisualStudio/18.vNext.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Make Alt+F1 (momentary toggle) work for inlay hints. ([PR #19421](https://github.com/dotnet/fsharp/pull/19421))
* Fix doubled F# diagnostics in tooltips. ([Issue #16360](https://github.com/dotnet/fsharp/issues/16360))
* Fix `NotSupportedException` in the memory-mapped-file optimization when copying `ReadOnlyMemory` into `MemoryMappedFileViewStream`. ([Issue #20263](https://github.com/dotnet/fsharp/issues/20263))
* Go To Definition on a symbol declared in another project of the solution no longer opens a generated signature when the origin document comes from a solution snapshot that predates that project's documents: navigation, Find All References and Rename now look the target up in the workspace's current solution as well. ([PR #20462](https://github.com/dotnet/fsharp/pull/20462))

### Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,32 @@ type Solution with
| Some projectId -> self.TryGetDocumentIdFromFSharpRange(range, projectId)
| None -> self.TryGetDocumentIdFromFSharpRange range
|> Option.map self.GetDocument

type Document with

/// Runs a lookup against this document's solution and, when it finds nothing, against the
/// workspace's current solution: the document may come from a snapshot taken before every
/// project of the solution finished loading.
member document.TryFindInSolutions(find: Solution -> 'T voption) =
match find document.Project.Solution with
| ValueSome found -> ValueSome found
| ValueNone -> find document.Project.Solution.Workspace.CurrentSolution

/// Every document with the file path, from whichever project includes it.
member document.GetSolutionDocumentsWithFilePath(filePath: string) =
let filePath = Path.GetFullPathSafe filePath

document.TryFindInSolutions(fun solution ->
match solution.GetDocumentIdsWithFilePath filePath with
| ids when ids.IsEmpty -> ValueNone
| ids -> ValueSome [ for id in ids -> solution.GetDocument id ])
|> ValueOption.defaultValue []

member document.TryGetSolutionDocumentFromPath(filePath: string) =
document.GetSolutionDocumentsWithFilePath filePath |> Seq.tryHeadV

/// The document for the range's file, preferring this document's project or one it depends on.
member document.TryGetSolutionDocumentFromFSharpRange(range: range) =
document.TryFindInSolutions(fun solution ->
solution.TryGetDocumentFromFSharpRange(range, document.Project.Id)
|> ValueOption.ofOption)
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ module internal SymbolHelpers =
let otherFile = getOtherFile currentDocument.FilePath

let! otherFileCheckResults =
match currentDocument.Project.Solution.TryGetDocumentFromPath otherFile with
match currentDocument.TryGetSolutionDocumentFromPath otherFile with
| ValueSome doc ->
cancellableTask {
let! _, checkFileResults = doc.GetFSharpParseAndCheckResultsAsync("findReferencedSymbolsAsync")
Expand Down
8 changes: 3 additions & 5 deletions vsintegration/src/FSharp.Editor/LanguageService/Symbols.fs
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,9 @@ type FSharpSymbolUse with
Some(SymbolScope.Projects([ currentDocument.Project ], isSymbolLocalForProject))
else
let projects =
currentDocument.Project.Solution.GetDocumentIdsWithFilePath(filePath)
|> Seq.map (fun x -> x.ProjectId)
|> Seq.distinct
|> Seq.map currentDocument.Project.Solution.GetProject
|> Seq.toList
currentDocument.GetSolutionDocumentsWithFilePath filePath
|> List.map _.Project
|> List.distinctBy _.Id

match projects with
| [] -> None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,15 @@ module FSharpFindUsagesService =
}

// File can be included in more than one project, hence single `range` may results with multiple `Document`s.
let rangeToDocumentSpans (solution: Solution, range: range, symbolName: string) =
let rangeToDocumentSpans (document: Document, range: range, symbolName: string) =
if range.Start = range.End then
CancellableTask.singleton [||]
else
cancellableTask {
let documentIds = solution.GetDocumentIdsWithFilePath(range.FileName)

let! spans =
seq {
for documentId in documentIds do
for doc in document.GetSolutionDocumentsWithFilePath range.FileName do
cancellableTask {
let doc = solution.GetDocument(documentId)
let! cancellationToken = CancellableTask.getCancellationToken ()
let! sourceText = doc.GetTextAsync(cancellationToken)

Expand Down Expand Up @@ -119,7 +116,7 @@ module FSharpFindUsagesService =

let! declarationSpans =
match declarationRange with
| Some range -> rangeToDocumentSpans (document.Project.Solution, range, symbol.Ident.idText)
| Some range -> rangeToDocumentSpans (document, range, symbol.Ident.idText)
| None -> CancellableTask.singleton [||]

let declarationSpans =
Expand Down
Loading
Loading