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/.FSharp.Compiler.Service/11.0.200.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
### Added

* F# Interactive gains a JSON-RPC server mode, `--fsi-server-jsonrpc:<pipe name>`, in which a host submits interactions over a named pipe and receives structured results — diagnostics with positions, escaping exceptions, the values each interaction bound, and the session's own process id — instead of recovering them by looking for a `SERVER-PROMPT>` marker in the output text. Program output continues to flow through the redirected console streams. The pipe admits only the user running the session; `--fsi-server-client-pid:<pid>` names the host process whose exit ends the session. `FsiEvaluationSession` exposes both options as `JsonRpcServerPipeName` and `JsonRpcClientProcessId`. The mode is part of the .NET fsi only. ([PR #20396](https://github.com/dotnet/fsharp/pull/20396))
* `XmlDoc` keeps the range of every `///` line (`LineRanges`) and lists the `name` and `cref` attribute values it contains with their source ranges (`GetRefs`). The checker reports each `<param>`, `<paramref>`, `<typeparam>` and `<typeparamref>` name that matches a parameter or type parameter of the documented declaration as a `RelatedSymbolUseKind.XmlDocParameter` use, which `GetUsesOfSymbolInFile` returns only when asked for and Find All References and semantic classification never see. ([Issue #20630](https://github.com/dotnet/fsharp/issues/20630), [Issue #15134](https://github.com/dotnet/fsharp/issues/15134), [PR #20637](https://github.com/dotnet/fsharp/pull/20637))

### Fixed

Expand Down
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 @@ -9,6 +9,7 @@
* Peek Definition on an F# symbol whose definition lives in metadata no longer deadlocks Visual Studio. Peek holds the main thread in `JoinableTaskFactory.Run` without pumping messages while it asks the language service for the definition, and generating the metadata document needs that same thread; Peek now stops at definitions that already have a document, and Go To Definition, which owns the wait it makes, still opens the generated one. ([PR #20503](https://github.com/dotnet/fsharp/pull/20503))
* Improve Find All References performance by throttling parallel typechecks. ([PR #20128](https://github.com/dotnet/fsharp/pull/20128))
* Fixed Rename incorrectly renaming `get` and `set` keywords for properties with explicit accessors. ([Issue #18270](https://github.com/dotnet/fsharp/issues/18270), [PR #19252](https://github.com/dotnet/fsharp/pull/19252))
* Rename rewrites the `<param>`, `<paramref>`, `<typeparam>` and `<typeparamref>` tags of the renamed parameter or type parameter in the declaration's `///` comment, and document highlights include them; Find All References leaves them out. ([Issue #20630](https://github.com/dotnet/fsharp/issues/20630), [PR #20638](https://github.com/dotnet/fsharp/pull/20638))
* Fixed Find All References crash when F# project contains non-F# files like `.cshtml`. ([Issue #16394](https://github.com/dotnet/fsharp/issues/16394), [PR #19252](https://github.com/dotnet/fsharp/pull/19252))
* Avoid using `cancellableTask` in `DocumentCache`; the editor cache now uses direct `CancellationToken`-aware `task` wrappers, avoiding the background `Task.Run` offload and a larger wrapper closure from the `cancellableTask` builder. ([Issue #20268](https://github.com/dotnet/fsharp/issues/20268))
* Cache document diagnostics by version stamp, so an unchanged document is not reanalyzed on every crawler pass. ([Issue #20120](https://github.com/dotnet/fsharp/issues/20120), [PR #20121](https://github.com/dotnet/fsharp/pull/20121))
Expand Down
11 changes: 11 additions & 0 deletions src/Compiler/Checking/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,16 @@ module TcRecdUnionAndEnumDeclarations =

let checkXmlDocs = cenv.diagnosticOptions.CheckXmlDocs
let xmlDoc = xmldoc.ToXmlDoc(checkXmlDocs, Some names)

match parent with
| Parent tcref ->
let fields =
[ for i, f in List.indexed rfields do
if not f.rfield_name_generated then
f.LogicalName, Item.UnionCaseField (UnionCaseInfo (thisTyInst, UnionCaseRef (tcref, id.idText)), i) ]
ReportXmlDocRefUses cenv.tcSink xmlDoc fields []
| ParentNone -> ()

let attrs, getFinalAttrs, _ = TcAttributesCanFail cenv env AttributeTargets.UnionCaseDecl synAttrs
let unionCase = Construct.NewUnionCase id rfields recordTy attrs xmlDoc vis

Expand Down Expand Up @@ -2935,6 +2945,7 @@ module EstablishTypeDefinitionCores =

let checkXmlDocs = cenv.diagnosticOptions.CheckXmlDocs
let xmlDoc = xmlDoc.ToXmlDoc(checkXmlDocs, Some paramNames )
ReportXmlDocRefUses cenv.tcSink xmlDoc [] [ for tp in checkedTypars -> tp.Name, Item.TypeVar(tp.Name, tp) ]
Construct.NewTycon
(cpath, id.idText, id.idRange, vis, visOfRepr, TyparKind.Type, LazyWithContext.NotLazy checkedTypars,
xmlDoc, preferPostfix, preEstablishedHasDefaultCtor, hasSelfReferentialCtor, lmodTy)
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/Checking/CheckIncrementalClasses.fs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@ let TcImplicitCtorInfo_Phase2A(cenv: cenv, env, tpenv, tcref: TyconRef, vis, att
let checkXmlDocs = cenv.diagnosticOptions.CheckXmlDocs
let xmlDoc = xmlDoc.ToXmlDoc(checkXmlDocs, Some paramNames)
let ctorVal = MakeAndPublishVal cenv env (Parent tcref, false, ModuleOrMemberBinding, ValInRecScope isComplete, ctorValScheme, attribs, xmlDoc, None, false)

// The `<param>` tags of a primary constructor live on the type's doc
let ctorParameters = [ for v in ctorArgs -> v.LogicalName, Item.Value(mkLocalValRef v) ]
ReportXmlDocRefUses cenv.tcSink xmlDoc ctorParameters []
ReportXmlDocRefUses cenv.tcSink tcref.Deref.XmlDoc ctorParameters []
ctorValScheme, ctorVal

let thisVal =
Expand Down
18 changes: 16 additions & 2 deletions src/Compiler/Checking/Expressions/CheckExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11759,6 +11759,18 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt
if isFixed then TcAndBuildFixedExpr cenv env (overallPatTy, rhsExprChecked, overallExprTy, mBinding)
else rhsExprChecked

// The parameters of a function binding are the binders of its outer lambda chain
let rec parameterVals expr =
match stripDebugPoints expr with
| Expr.Lambda (_, _, _, vs, body, _, _) ->
[ for v in vs do
if not (v.IsMemberThisVal || v.IsCtorThisVal || v.IsCompilerGenerated) then
v.LogicalName, Item.Value(mkLocalValRef v) ]
@ parameterVals body
| _ -> []

ReportXmlDocRefUses cenv.tcSink xmlDoc (parameterVals rhsExprChecked) [ for tp in declaredTypars -> tp.Name, Item.TypeVar(tp.Name, tp) ]

match apinfoOpt with
| Some (apinfo, apOverallTy, m) ->
let activePatResTys = NewInferenceTypes g apinfo.ActiveTags
Expand Down Expand Up @@ -13665,9 +13677,10 @@ let private PublishArguments (cenv: cenv) (env: TcEnv) vspec (synValSig: SynValS
|> Seq.collect (fun x -> x ||> Seq.zip)
|> Seq.choose (fun (synArgInfo, argInfo) -> synArgInfo.Ident |> Option.map (pair argInfo))

for (argTy, argReprInfo), ident in argData do
[ for (argTy, argReprInfo), ident in argData do
let item = Item.OtherName (Some ident, argTy, Some argReprInfo, None, ident.idRange)
CallNameResolutionSink cenv.tcSink (ident.idRange, env.NameEnv, item, emptyTyparInst, ItemOccurrence.Binding, env.AccessRights)
ident.idText, item ]

let TcAndPublishValSpec (cenv: cenv, env, containerInfo: ContainerInfo, declKind : DeclKind, memFlagsOpt, tpenv, synValSig) =

Expand Down Expand Up @@ -13756,7 +13769,8 @@ let TcAndPublishValSpec (cenv: cenv, env, containerInfo: ContainerInfo, declKind

let vspec = MakeAndPublishVal cenv env (altActualParent, true, declKind, ValNotInRecScope, valscheme, attrs, xmlDoc, literalValue, isGeneratedEventVal)

PublishArguments cenv env vspec synValSig allDeclaredTypars.Length
let parameters = PublishArguments cenv env vspec synValSig allDeclaredTypars.Length
ReportXmlDocRefUses cenv.tcSink xmlDoc parameters [ for tp in allDeclaredTypars -> tp.Name, Item.TypeVar(tp.Name, tp) ]

assert(vspec.InlineInfo = inlineFlag)

Expand Down
21 changes: 21 additions & 0 deletions src/Compiler/Checking/NameResolution.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
/// Name environment and name resolution
module internal FSharp.Compiler.NameResolution

open System
open System.Collections.Generic

open Internal.Utilities.Collections
Expand Down Expand Up @@ -33,6 +34,7 @@ open FSharp.Compiler.TypedTree
open FSharp.Compiler.TypedTreeBasics
open FSharp.Compiler.TypedTreeOps
open FSharp.Compiler.TypeHierarchy
open FSharp.Compiler.Xml

#if !NO_TYPEPROVIDERS
open FSharp.Compiler.TypeProviders
Expand Down Expand Up @@ -2653,6 +2655,25 @@ let CallRelatedSymbolSink (sink: TcResultsSink) (m: range, item: Item, kind: Rel
| None -> ()
| Some currentSink -> currentSink.NotifyRelatedSymbolUse(m, item, kind)

/// Report each `<param name>`/`<paramref name>`/`<typeparam name>`/`<typeparamref name>` of a declaration's XML doc
/// as a related use of the parameter or type parameter it names, at the range of the attribute value.
let ReportXmlDocRefUses (sink: TcResultsSink) (doc: XmlDoc) (parameters: (string * Item) list) (typars: (string * Item) list) =
match sink.CurrentSink with
| Some currentSink when doc.NonEmpty && (not parameters.IsEmpty || not typars.IsEmpty) ->
for docRef in doc.GetRefs() do
let candidates =
match docRef.Kind with
| XmlDocRefKind.Param
| XmlDocRefKind.ParamRef -> parameters
| XmlDocRefKind.TypeParam
| XmlDocRefKind.TypeParamRef -> typars
| XmlDocRefKind.Cref -> []

for name, item in candidates do
if String.Equals(name, docRef.Text, StringComparison.Ordinal) then
currentSink.NotifyRelatedSymbolUse(docRef.Range, item, RelatedSymbolUseKind.XmlDocParameter)
| _ -> ()

/// Report a specific expression typing at a source range
let CallExprHasTypeSink (sink: TcResultsSink) (m: range, nenv, ty, ad) =
match sink.CurrentSink with
Expand Down
6 changes: 6 additions & 0 deletions src/Compiler/Checking/NameResolution.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ open FSharp.Compiler.Text
open FSharp.Compiler.TypedTree
open FSharp.Compiler.TypedTreeOps
open FSharp.Compiler.TcGlobals
open FSharp.Compiler.Xml

exception NoConstructorsAvailableForType of TType * DisplayEnv * range

Expand Down Expand Up @@ -654,6 +655,11 @@ val internal RegisterUnionCaseTesterForProperty: TcResultsSink -> identRange: ra
/// Report a related symbol use at a source range (does not affect colorization or symbol info)
val internal CallRelatedSymbolSink: TcResultsSink -> range * Item * RelatedSymbolUseKind -> unit

/// Report each `<param name>`/`<paramref name>`/`<typeparam name>`/`<typeparamref name>` of a declaration's XML doc
/// as a related use of the parameter or type parameter it names, at the range of the attribute value.
val internal ReportXmlDocRefUses:
TcResultsSink -> doc: XmlDoc -> parameters: (string * Item) list -> typars: (string * Item) list -> unit

/// Report a specific name resolution at a source range
val internal CallExprHasTypeSink: TcResultsSink -> range * NameResolutionEnv * TType * AccessorDomain -> unit

Expand Down
3 changes: 3 additions & 0 deletions src/Compiler/Checking/RelatedSymbolUse.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ type RelatedSymbolUseKind =
| UnionCaseTester = 1
/// Record type via copy-and-update expression (e.g., { r with ... } → RecordType)
| CopyAndUpdateRecord = 2
/// Parameter or type parameter via the `name` of a `param`, `paramref`, `typeparam` or `typeparamref`
/// tag in the declaration's XML doc
| XmlDocParameter = 4
/// All related symbol kinds
| All = 0x7FFFFFFF
5 changes: 3 additions & 2 deletions src/Compiler/Service/IncrementalBuild.fs
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,10 @@ type BoundModel private (
if not r.IsSynthetic && preventDuplicates.Add struct(r.Start, r.End) then
builder.Write(cnr.Range, cnr.Item))

// A name inside a `///` comment is for rename and highlighting, not for symbol search
sResolutions.CapturedRelatedSymbolUses
|> Seq.iter (fun (m, item, _kind) ->
if not m.IsSynthetic then
|> Seq.iter (fun (m, item, kind) ->
if not m.IsSynthetic && kind <> RelatedSymbolUseKind.XmlDocParameter then
builder.Write(m, item))

let semanticClassification = sResolutions.GetSemanticClassification(tcGlobals, tcImports.GetImportMap(), sink.GetFormatSpecifierLocations(), None, RelatedSymbolUseKind.All)
Expand Down
3 changes: 2 additions & 1 deletion src/Compiler/Service/SemanticClassification.fs
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,8 @@ module TcResolutionsExtensions =
match relatedSymbolKinds with
| Some kinds ->
for (m, item, kind) in sResolutions.CapturedRelatedSymbolUses do
if kinds.HasFlag kind then
// A name inside a `///` comment is never classified, whatever the caller asked for
if kinds.HasFlag kind && kind <> RelatedSymbolUseKind.XmlDocParameter then
match range, item with
| Some r, _ when not (rangeContainsPos r m.Start || rangeContainsPos r m.End) -> ()
| _, Item.UnionCase _ -> results.Add(SemanticClassificationItem((m, SemanticClassificationType.UnionCase)))
Expand Down
5 changes: 3 additions & 2 deletions src/Compiler/Service/TransparentCompiler.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2094,9 +2094,10 @@ type internal TransparentCompiler
if not r.IsSynthetic && preventDuplicates.Add struct (r.Start, r.End) then
builder.Write(cnr.Range, cnr.Item))

// A name inside a `///` comment is for rename and highlighting, not for symbol search
sResolutions.CapturedRelatedSymbolUses
|> Seq.iter (fun (m, item, _kind) ->
if not m.IsSynthetic then
|> Seq.iter (fun (m, item, kind) ->
if not m.IsSynthetic && kind <> RelatedSymbolUseKind.XmlDocParameter then
builder.Write(m, item))

builder.TryBuildAndReset())
Expand Down
Loading
Loading