Skip to content
This repository was archived by the owner on Dec 23, 2024. It is now read-only.

Commit deb425a

Browse files
authored
[VS] Get source text of an Entity symbol's signature for viewing metadata (dotnet#11325)
* Initial work for generating a signature of a given symbol for viewing metadata * Do not output the 'event' keyword * Adding open paths and fixing surface area * Fixing tests. Adding more extensions to Project and Document. Better handling of determining if we should do semantic diagnostics for a given file. * Trying to go to definition on metadata. Managing metadata as source projects. * Navigating to external symbol * ignoring tests * Renaming TryGenerateSignatureText to TryGetMetadataText * Fixing namespace and some parts of module
1 parent 180ed30 commit deb425a

14 files changed

+278
-188
lines changed

Common/Constants.fs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ module internal FSharpConstants =
5151
/// "F# Miscellaneous Files"
5252
let FSharpMiscellaneousFilesName = "F# Miscellaneous Files"
5353

54+
[<Literal>]
55+
/// "F# Metadata"
56+
let FSharpMetadataName = "F# Metadata"
57+
5458
[<RequireQualifiedAccess>]
5559
module internal FSharpProviderConstants =
5660

Common/Extensions.fs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ open FSharp.Compiler.EditorServices
1515
open FSharp.Compiler.Syntax
1616
open FSharp.Compiler.Text
1717

18+
open Microsoft.VisualStudio.FSharp.Editor
19+
1820
type private FSharpGlyph = FSharp.Compiler.EditorServices.FSharpGlyph
1921
type private FSharpRoslynGlyph = Microsoft.CodeAnalysis.ExternalAccess.FSharp.FSharpGlyph
2022

@@ -36,6 +38,11 @@ type ProjectId with
3638
member this.ToFSharpProjectIdString() =
3739
this.Id.ToString("D").ToLowerInvariant()
3840

41+
type Project with
42+
member this.IsFSharpMiscellaneous = this.Name = FSharpConstants.FSharpMiscellaneousFilesName
43+
member this.IsFSharpMetadata = this.Name.StartsWith(FSharpConstants.FSharpMetadataName)
44+
member this.IsFSharpMiscellaneousOrMetadata = this.IsFSharpMiscellaneous || this.IsFSharpMetadata
45+
3946
type Document with
4047
member this.TryGetLanguageService<'T when 'T :> ILanguageService>() =
4148
match this.Project with
@@ -47,6 +54,9 @@ type Document with
4754
languageServices.GetService<'T>()
4855
|> Some
4956

57+
member this.IsFSharpScript =
58+
isScriptFile this.FilePath
59+
5060
module private SourceText =
5161

5262
open System.Runtime.CompilerServices

Diagnostics/DocumentDiagnosticAnalyzer.fs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ type internal FSharpDocumentDiagnosticAnalyzer
115115
interface IFSharpDocumentDiagnosticAnalyzer with
116116

117117
member this.AnalyzeSyntaxAsync(document: Document, cancellationToken: CancellationToken): Task<ImmutableArray<Diagnostic>> =
118+
if document.Project.IsFSharpMetadata then Task.FromResult(ImmutableArray.Empty)
119+
else
120+
118121
asyncMaybe {
119122
let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName)
120123
return!
@@ -125,14 +128,14 @@ type internal FSharpDocumentDiagnosticAnalyzer
125128
|> RoslynHelpers.StartAsyncAsTask cancellationToken
126129

127130
member this.AnalyzeSemanticsAsync(document: Document, cancellationToken: CancellationToken): Task<ImmutableArray<Diagnostic>> =
131+
if document.Project.IsFSharpMiscellaneousOrMetadata && not document.IsFSharpScript then Task.FromResult(ImmutableArray.Empty)
132+
else
133+
128134
asyncMaybe {
129135
let! parsingOptions, _, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document, cancellationToken, userOpName)
130-
if document.Project.Name <> FSharpConstants.FSharpMiscellaneousFilesName || isScriptFile document.FilePath then
131-
return!
132-
FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(checkerProvider.Checker, document, parsingOptions, projectOptions, DiagnosticsType.Semantic)
133-
|> liftAsync
134-
else
135-
return ImmutableArray<Diagnostic>.Empty
136+
return!
137+
FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(checkerProvider.Checker, document, parsingOptions, projectOptions, DiagnosticsType.Semantic)
138+
|> liftAsync
136139
}
137140
|> Async.map (Option.defaultValue ImmutableArray<Diagnostic>.Empty)
138141
|> RoslynHelpers.StartAsyncAsTask cancellationToken

Diagnostics/SimplifyNameDiagnosticAnalyzer.fs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ type internal SimplifyNameDiagnosticAnalyzer
3434
interface IFSharpSimplifyNameDiagnosticAnalyzer with
3535

3636
member _.AnalyzeSemanticsAsync(descriptor, document: Document, cancellationToken: CancellationToken) =
37+
if document.Project.IsFSharpMiscellaneousOrMetadata && not document.IsFSharpScript then Tasks.Task.FromResult(ImmutableArray.Empty)
38+
else
39+
3740
asyncMaybe {
3841
do! Option.guard document.FSharpOptions.CodeFixes.SimplifyName
3942
do Trace.TraceInformation("{0:n3} (start) SimplifyName", DateTime.Now.TimeOfDay.TotalSeconds)

Diagnostics/UnusedDeclarationsAnalyzer.fs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ type internal UnusedDeclarationsAnalyzer
2424
interface IFSharpUnusedDeclarationsDiagnosticAnalyzer with
2525

2626
member _.AnalyzeSemanticsAsync(descriptor, document, cancellationToken) =
27+
if document.Project.IsFSharpMiscellaneousOrMetadata && not document.IsFSharpScript then Threading.Tasks.Task.FromResult(ImmutableArray.Empty)
28+
else
29+
2730
asyncMaybe {
2831
do! Option.guard document.FSharpOptions.CodeFixes.UnusedDeclarations
2932

Diagnostics/UnusedOpensDiagnosticAnalyzer.fs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ type internal UnusedOpensDiagnosticAnalyzer
3838
interface IFSharpUnusedOpensDiagnosticAnalyzer with
3939

4040
member _.AnalyzeSemanticsAsync(descriptor, document: Document, cancellationToken: CancellationToken) =
41+
if document.Project.IsFSharpMiscellaneousOrMetadata && not document.IsFSharpScript then Tasks.Task.FromResult(ImmutableArray.Empty)
42+
else
43+
4144
asyncMaybe {
4245
do Trace.TraceInformation("{0:n3} (start) UnusedOpensAnalyzer", DateTime.Now.TimeOfDay.TotalSeconds)
4346
let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName)

FSharp.Editor.fsproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
<Compile Include="Common\Logger.fsi" />
2929
<Compile Include="Common\Logger.fs" />
3030
<Compile Include="Common\Pervasive.fs" />
31-
<Compile Include="Common\Extensions.fs" />
3231
<Compile Include="Common\Constants.fs" />
32+
<Compile Include="Common\Extensions.fs" />
3333
<Compile Include="Common\Error.fs" />
3434
<Compile Include="Common\Logging.fs" />
3535
<Compile Include="Common\RoslynHelpers.fs" />

LanguageService/FSharpCheckerProvider.fs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ open Microsoft.CodeAnalysis
1212
open Microsoft.VisualStudio
1313
open Microsoft.VisualStudio.FSharp.Editor
1414
open Microsoft.VisualStudio.LanguageServices
15+
open Microsoft.VisualStudio.LanguageServices.ProjectSystem
1516
open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Diagnostics
1617

1718
#nowarn "9" // NativePtr.toNativeInt
@@ -23,10 +24,11 @@ type internal FSharpCheckerProvider
2324
(
2425
analyzerService: IFSharpDiagnosticAnalyzerService,
2526
[<Import(typeof<VisualStudioWorkspace>)>] workspace: VisualStudioWorkspace,
27+
projectContextFactory: IWorkspaceProjectContextFactory,
2628
settings: EditorOptions
2729
) =
2830

29-
let metadataAsSource = FSharpMetadataAsSourceService()
31+
let metadataAsSource = FSharpMetadataAsSourceService(projectContextFactory)
3032

3133
let tryGetMetadataSnapshot (path, timeStamp) =
3234
try

LanguageService/FSharpProjectOptionsManager.fs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -259,16 +259,22 @@ type private FSharpProjectOptionsReactor (workspace: Workspace, settings: Editor
259259
// For now, disallow miscellaneous workspace since we are using the hacky F# miscellaneous files project.
260260
if document.Project.Solution.Workspace.Kind = WorkspaceKind.MiscellaneousFiles then
261261
reply.Reply None
262-
elif document.Project.Name = FSharpConstants.FSharpMiscellaneousFilesName then
262+
elif document.Project.IsFSharpMiscellaneousOrMetadata then
263263
let! options = tryComputeOptionsByFile document ct userOpName
264-
reply.Reply options
264+
if ct.IsCancellationRequested then
265+
reply.Reply None
266+
else
267+
reply.Reply options
265268
else
266269
// We only care about the latest project in the workspace's solution.
267270
// We do this to prevent any possible cache thrashing in FCS.
268271
let project = document.Project.Solution.Workspace.CurrentSolution.GetProject(document.Project.Id)
269272
if not (isNull project) then
270273
let! options = tryComputeOptions project ct
271-
reply.Reply options
274+
if ct.IsCancellationRequested then
275+
reply.Reply None
276+
else
277+
reply.Reply options
272278
else
273279
reply.Reply None
274280
with
@@ -280,26 +286,37 @@ type private FSharpProjectOptionsReactor (workspace: Workspace, settings: Editor
280286
reply.Reply None
281287
else
282288
try
283-
if project.Solution.Workspace.Kind = WorkspaceKind.MiscellaneousFiles || project.Name = FSharpConstants.FSharpMiscellaneousFilesName then
289+
if project.Solution.Workspace.Kind = WorkspaceKind.MiscellaneousFiles || project.IsFSharpMiscellaneousOrMetadata then
284290
reply.Reply None
285291
else
286292
// We only care about the latest project in the workspace's solution.
287293
// We do this to prevent any possible cache thrashing in FCS.
288294
let project = project.Solution.Workspace.CurrentSolution.GetProject(project.Id)
289295
if not (isNull project) then
290296
let! options = tryComputeOptions project ct
291-
reply.Reply options
297+
if ct.IsCancellationRequested then
298+
reply.Reply None
299+
else
300+
reply.Reply options
292301
else
293302
reply.Reply None
294303
with
295304
| _ ->
296305
reply.Reply None
297306

298307
| FSharpProjectOptionsMessage.ClearOptions(projectId) ->
299-
cache.TryRemove(projectId) |> ignore
308+
match cache.TryRemove(projectId) with
309+
| true, (_, _, projectOptions) ->
310+
checkerProvider.Checker.ClearCache([projectOptions])
311+
| _ ->
312+
()
300313
legacyProjectSites.TryRemove(projectId) |> ignore
301314
| FSharpProjectOptionsMessage.ClearSingleFileOptionsCache(documentId) ->
302-
singleFileCache.TryRemove(documentId) |> ignore
315+
match singleFileCache.TryRemove(documentId) with
316+
| true, (_, _, projectOptions) ->
317+
checkerProvider.Checker.ClearCache([projectOptions])
318+
| _ ->
319+
()
303320
}
304321

305322
let agent = MailboxProcessor.Start((fun agent -> loop agent), cancellationToken = cancellationTokenSource.Token)
@@ -362,6 +379,13 @@ type internal FSharpProjectOptionsManager
362379
| _ -> ()
363380
)
364381

382+
workspace.DocumentClosed.Add(fun args ->
383+
let doc = args.Document
384+
let proj = doc.Project
385+
if proj.Language = LanguageNames.FSharp && proj.IsFSharpMiscellaneousOrMetadata then
386+
reactor.ClearSingleFileOptionsCache(doc.Id)
387+
)
388+
365389
member _.SetLegacyProjectSite (projectId, projectSite) =
366390
reactor.SetLegacyProjectSite (projectId, projectSite)
367391

LanguageService/LanguageService.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ type private FSharpSolutionEvents(projectManager: FSharpProjectOptionsManager) =
6161

6262
member _.OnAfterCloseSolution(_) =
6363
projectManager.Checker.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients()
64+
projectManager.MetadataAsSource.ClearGeneratedFiles()
6465
VSConstants.S_OK
6566

6667
member _.OnAfterLoadProject(_, _) = VSConstants.E_NOTIMPL

0 commit comments

Comments
 (0)