Skip to content

Commit d29135c

Browse files
committed
RIDER-16740 Debugger: fix missing local F# values in editor
GitOrigin-RevId: fb9c7d66cd30bc4ee0ff49d670fa0ccfbb66791a
1 parent 8204ca8 commit d29135c

File tree

5 files changed

+140
-187
lines changed

5 files changed

+140
-187
lines changed

ReSharper.FSharp/src/FSharp/FSharp.Psi.Features/src/CodeCompletion/Rules/ImportModuleMemberRule.fs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.CodeCompletion
1616
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util
1717
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
1818
open JetBrains.ReSharper.Plugins.FSharp.Psi.Resolve
19+
open JetBrains.ReSharper.Plugins.FSharp.Psi.Services.Util
1920
open JetBrains.ReSharper.Plugins.FSharp.Psi.Services.Util.FSharpCompletionUtil
2021
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
2122
open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
@@ -96,7 +97,7 @@ type ImportModuleMemberRule() =
9697
match referenceContext.Value with
9798
| FSharpReferenceContext.Expression ->
9899
let treeNode = reparsedContext.TreeNode
99-
context.GetOrCreateDataUnderLock(LocalValuesRule.valuesKey, treeNode, LocalValuesRule.getLocalValues)
100+
context.GetOrCreateDataUnderLock(LocalValuesUtil.valuesKey, treeNode, LocalValuesUtil.getLocalValues)
100101

101102
| _ -> EmptyDictionary.Instance
102103

ReSharper.FSharp/src/FSharp/FSharp.Psi.Features/src/CodeCompletion/Rules/LocalValuesRule.fs

Lines changed: 4 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.CodeCompletion.Rules
22

3-
open System.Collections.Generic
43
open FSharp.Compiler.CodeAnalysis
5-
open JetBrains.Application
64
open JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure
75
open JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure.AspectLookupItems.BaseInfrastructure
86
open JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure.AspectLookupItems.Behaviors
@@ -13,12 +11,11 @@ open JetBrains.ReSharper.Plugins.FSharp.Psi
1311
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.CodeCompletion
1412
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util
1513
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util.FcsTypeUtil
14+
open JetBrains.ReSharper.Plugins.FSharp.Psi.Services.Util
1615
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
1716
open JetBrains.ReSharper.Plugins.FSharp.Util
1817
open JetBrains.ReSharper.Psi
19-
open JetBrains.ReSharper.Psi.Tree
2018
open JetBrains.UI.RichText
21-
open JetBrains.Util
2219

2320
type FcsSymbolInfo(text, symbolUse: FSharpSymbolUse) =
2421
inherit TextualInfo(text, text)
@@ -31,116 +28,6 @@ type FcsSymbolInfo(text, symbolUse: FSharpSymbolUse) =
3128
member this.FcsSymbolUse = symbolUse
3229
member this.NamespaceToOpen = [||]
3330

34-
module rec LocalValuesRule =
35-
let valuesKey = Key<IDictionary<string, FSharpSymbolUse>>(nameof LocalValuesRule)
36-
37-
let getLocalValues (context: ITreeNode) : IDictionary<_, _> =
38-
let values = Dictionary<string, FSharpSymbolUse>()
39-
40-
let addValue (decl: IFSharpDeclaration) =
41-
let sourceName = decl.SourceName
42-
if sourceName <> "_" then
43-
values.TryAdd(sourceName, decl.GetFcsSymbolUse()) |> ignore
44-
45-
let addPatternValues (pat: IFSharpPattern) =
46-
if isNull pat then () else
47-
48-
for declPattern in pat.Declarations do
49-
let pat = declPattern.As<IFSharpPattern>()
50-
if pat.IsDeclaration then
51-
addValue declPattern
52-
53-
let addLetBindingsValues (letBindings: ILetBindings) =
54-
for otherBinding in letBindings.Bindings do
55-
addPatternValues otherBinding.HeadPattern
56-
57-
let addSelfIdValue (selfId: ISelfId) =
58-
if isNotNull selfId then
59-
addValue selfId
60-
61-
let addMembersValues (contextOffset: int) (members: ITreeNode seq) =
62-
let members = members |> Seq.takeWhile (fun m -> m.GetTreeStartOffset().Offset < contextOffset)
63-
64-
for otherMember in members do
65-
match otherMember with
66-
| :? ILetBindings as letBindings ->
67-
for binding in letBindings.Bindings do
68-
addPatternValues binding.HeadPattern
69-
70-
| _ -> ()
71-
72-
for parentNode in context.ContainingNodes() do
73-
Interruption.Current.CheckAndThrow()
74-
75-
match parentNode with
76-
| :? IMatchClause as matchClause ->
77-
addPatternValues matchClause.Pattern
78-
79-
| :? IBinding as binding ->
80-
Seq.iter addPatternValues binding.ParameterPatterns
81-
82-
let letBindings = LetBindingsNavigator.GetByBinding(binding)
83-
if isNotNull letBindings && letBindings.IsRecursive then
84-
addLetBindingsValues letBindings
85-
86-
| :? IAccessorDeclaration as decl ->
87-
Seq.iter addPatternValues decl.ParameterPatternsEnumerable
88-
89-
| :? IFSharpTypeDeclaration as typeDecl ->
90-
let ctorDecl = typeDecl.PrimaryConstructorDeclaration
91-
if isNotNull ctorDecl then
92-
addPatternValues ctorDecl.ParameterPatterns
93-
addSelfIdValue ctorDecl.SelfIdentifier
94-
95-
| :? IFSharpExpression as expr ->
96-
let letExpr = LetOrUseExprNavigator.GetByInExpression(expr)
97-
if isNotNull letExpr then
98-
addLetBindingsValues letExpr
99-
100-
match expr with
101-
| :? ILambdaExpr as lambdaExpr ->
102-
for pattern in lambdaExpr.PatternsEnumerable do
103-
addPatternValues pattern
104-
105-
| :? IForEachExpr as forExpr ->
106-
addPatternValues forExpr.Pattern
107-
108-
| :? IForExpr as forExpr ->
109-
addValue forExpr.Identifier
110-
111-
| _ -> ()
112-
113-
| :? IModuleMember as moduleMember ->
114-
let moduleDecl = ModuleLikeDeclarationNavigator.GetByMember(moduleMember)
115-
if isNotNull moduleDecl then
116-
let isRecursive =
117-
match moduleDecl with
118-
| :? IDeclaredModuleLikeDeclaration as moduleDecl -> moduleDecl.IsRecursive
119-
| _ -> false
120-
121-
let contextOffset =
122-
if isRecursive then moduleDecl.GetTreeEndOffset() else moduleMember.GetTreeStartOffset()
123-
124-
addMembersValues contextOffset.Offset (moduleDecl.MembersEnumerable |> Seq.cast)
125-
126-
let typeDecl = FSharpTypeDeclarationNavigator.GetByTypeMember(moduleMember.As())
127-
if isNotNull typeDecl then
128-
addMembersValues (moduleMember.GetTreeStartOffset().Offset) (typeDecl.TypeMembersEnumerable |> Seq.cast)
129-
130-
| :? ITypeBodyMemberDeclaration as typeMember ->
131-
let typeDecl = FSharpTypeDeclarationNavigator.GetByTypeMember(typeMember)
132-
if isNotNull typeDecl then
133-
addMembersValues (typeMember.GetTreeStartOffset().Offset) (typeDecl.TypeMembersEnumerable |> Seq.cast)
134-
135-
let memberDecl = typeMember.As<IMemberDeclaration>()
136-
if isNotNull memberDecl then
137-
addSelfIdValue memberDecl.SelfId
138-
Seq.iter addPatternValues memberDecl.ParameterPatterns
139-
140-
| _ -> ()
141-
142-
values
143-
14431
[<Language(typeof<FSharpLanguage>)>]
14532
type LocalValuesRule() =
14633
inherit ItemsProviderOfSpecificContext<FSharpCodeCompletionContext>()
@@ -157,9 +44,9 @@ type LocalValuesRule() =
15744
override this.AddLookupItems(context, collector) =
15845
let values =
15946
let treeNode = context.ReparsedContext.TreeNode
160-
context.GetOrCreateDataUnderLock(LocalValuesRule.valuesKey, treeNode, LocalValuesRule.getLocalValues)
47+
context.GetOrCreateDataUnderLock(LocalValuesUtil.valuesKey, treeNode, LocalValuesUtil.getLocalValues)
16148

162-
for KeyValue(name, fcsSymbolUse) in values do
49+
for KeyValue(name, (_, fcsSymbolUse)) in values do
16350
let icon = if isNull fcsSymbolUse then null else getIconId fcsSymbolUse.Symbol
16451

16552
let info = FcsSymbolInfo(name, fcsSymbolUse, Ranges = context.Ranges)
@@ -181,7 +68,7 @@ type LocalValuesRule() =
18168
false
18269

18370
override this.TransformItems(context, collector) =
184-
let values = context.GetData(LocalValuesRule.valuesKey)
71+
let values = context.GetData(LocalValuesUtil.valuesKey)
18572
if isNull values then () else
18673

18774
collector.RemoveWhere(fun item ->
Lines changed: 15 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,25 @@
11
namespace JetBrains.ReSharper.Plugins.FSharp.Services.Debugger
22

3-
open FSharp.Compiler.Syntax
4-
open FSharp.Compiler.Text
5-
open JetBrains.DocumentModel
63
open JetBrains.ReSharper.Feature.Services.Debugger
74
open JetBrains.ReSharper.Plugins.FSharp.Psi
5+
open JetBrains.ReSharper.Plugins.FSharp.Psi.Services.Util
86
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
9-
open JetBrains.ReSharper.Plugins.FSharp.Util
107
open JetBrains.ReSharper.Psi
118
open JetBrains.ReSharper.Psi.Tree
129

1310
[<Language(typeof<FSharpLanguage>)>]
14-
type FSharpDebuggerLocalSymbolProvider() =
11+
type FSharpDebuggerLocalSymbolProvider2() =
1512
interface IDebuggerLocalSymbolProvider with
16-
member x.FindLocalDeclarationAt(file: IFile, range: DocumentRange, name: string) =
17-
match file.AsFSharpFile() with
18-
| null -> null, null
19-
| fsFile ->
20-
21-
match fsFile.ParseTree with
22-
| None -> null, null
23-
| Some parseTree ->
24-
25-
let pos = getPosFromDocumentOffset range.EndOffset
26-
let mutable declRange = None
27-
28-
let visitor =
29-
let inline (|SuitableIdent|_|) (ident: Ident) =
30-
if ident.idText = name && (Position.posLt ident.idRange.End pos || Position.posEq ident.idRange.End pos) then
31-
Some ident.idRange
32-
else None
33-
34-
let updateDeclRange (range: Range) =
35-
match declRange with
36-
| None ->
37-
declRange <- Some range
38-
| Some oldDeclRange when Position.posGt range.Start oldDeclRange.Start ->
39-
declRange <- Some range
40-
| _ -> ()
41-
42-
let visitPat pat defaultTraverse =
43-
match pat with
44-
| SynPat.Named(SynIdent(SuitableIdent range, _), false, _, _) -> updateDeclRange range
45-
| _ -> ()
46-
defaultTraverse pat
47-
48-
{ new SyntaxVisitorBase<_>() with
49-
member this.VisitExpr(_, traverseSynExpr, defaultTraverse, expr) =
50-
match expr with
51-
| SynExpr.For(ident = SuitableIdent range) -> updateDeclRange range
52-
| SynExpr.ForEach(pat = pat) -> visitPat pat ignore
53-
| SynExpr.App(argExpr = SynExpr.Ident (SuitableIdent range)) -> updateDeclRange range
54-
| _ -> ()
55-
defaultTraverse expr
56-
57-
member this.VisitPat(_, defaultTraverse, pat) = visitPat pat defaultTraverse
58-
59-
member this.VisitLetOrUse(_, _, _, bindings, range) =
60-
bindings |> List.tryPick (fun (SynBinding(headPat = headPat)) ->
61-
visitPat headPat (fun _ -> None))
62-
63-
member this.VisitMatchClause(_, defaultTraverse, (SynMatchClause(pat, _, _, _, _, _) as clause)) =
64-
visitPat pat (fun _ -> None) |> Option.orElseWith (fun _ -> defaultTraverse clause) }
65-
66-
SyntaxTraversal.Traverse(pos, parseTree, visitor) |> ignore
67-
68-
match declRange with
69-
| Some declRange ->
70-
let endOffset = getTreeEndOffset range.Document declRange
71-
let treeNode = fsFile.FindTokenAt(endOffset - 1)
72-
match treeNode.GetContainingNode<IFSharpDeclaration>() with
73-
| null -> treeNode, null
74-
| declaration -> treeNode, declaration.DeclaredElement
75-
76-
| None -> null, null
77-
78-
member x.FindContainingFunctionDeclarationBody(treeNode) =
79-
treeNode // todo: refactor to get tree node instead of function declaration in SDK
13+
member this.FindLocalDeclarationAt(file, range, name) =
14+
let token = file.FindTokenAt(range.StartOffset)
15+
if isNull token then null, null else
16+
17+
let values = LocalValuesUtil.getLocalValues token
18+
match values.TryGetValue(name) with
19+
| false, _ -> null, null
20+
| true, (decl, _) -> decl, decl.DeclaredElement
21+
22+
member this.FindContainingFunctionDeclarationBody(node) =
23+
match node.GetContainingNode<IChameleonExpression>() with
24+
| null -> node.GetContainingFile()
25+
| chameleonExpr -> chameleonExpr

ReSharper.FSharp/src/FSharp/FSharp.Psi.Services/FSharp.Psi.Services.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
<Compile Include="src\Util\FSharpCodeCompletionContext.fs" />
6363
<Compile Include="src\Util\FSharpCompletionUtil.fs" />
6464
<Compile Include="src\Util\FSharpChangeTypeHelper.fs" />
65+
<Compile Include="src\Util\LocalValuesUtil.fs" />
6566
<Compile Include="src\Daemon\Highlightings\FSharpErrorUtil.fs" />
6667
<Compile Include="src\Daemon\Highlightings\ErrorHighlightings.fs" />
6768
<ErrorsGen Include="src\Daemon\Highlightings\Errors.xml">
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
module JetBrains.ReSharper.Plugins.FSharp.Psi.Services.Util.LocalValuesUtil
2+
3+
open System.Collections.Generic
4+
open FSharp.Compiler.CodeAnalysis
5+
open JetBrains.Application
6+
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
7+
open JetBrains.ReSharper.Psi.Tree
8+
open JetBrains.Util
9+
10+
let valuesKey = Key<IDictionary<string, IFSharpDeclaration * FSharpSymbolUse>>("LocalValuesUtil")
11+
12+
let getLocalValues (context: ITreeNode) : IDictionary<_, _> =
13+
let values = Dictionary<string, IFSharpDeclaration * FSharpSymbolUse>()
14+
15+
let addValue (decl: IFSharpDeclaration) =
16+
let sourceName = decl.SourceName
17+
if sourceName <> "_" then
18+
let symbolUse = decl.GetFcsSymbolUse()
19+
values.TryAdd(sourceName, (decl, symbolUse)) |> ignore
20+
21+
let addPatternValues (pat: IFSharpPattern) =
22+
if isNull pat then () else
23+
24+
for declPattern in pat.Declarations do
25+
let pat = declPattern.As<IFSharpPattern>()
26+
if pat.IsDeclaration then
27+
addValue declPattern
28+
29+
let addLetBindingsValues (letBindings: ILetBindings) =
30+
for otherBinding in letBindings.Bindings do
31+
addPatternValues otherBinding.HeadPattern
32+
33+
let addSelfIdValue (selfId: ISelfId) =
34+
if isNotNull selfId then
35+
addValue selfId
36+
37+
let addMembersValues (contextOffset: int) (members: ITreeNode seq) =
38+
let members = members |> Seq.takeWhile (fun m -> m.GetTreeStartOffset().Offset < contextOffset)
39+
40+
for otherMember in members do
41+
match otherMember with
42+
| :? ILetBindings as letBindings ->
43+
for binding in letBindings.Bindings do
44+
addPatternValues binding.HeadPattern
45+
46+
| _ -> ()
47+
48+
for parentNode in context.ContainingNodes() do
49+
Interruption.Current.CheckAndThrow()
50+
51+
match parentNode with
52+
| :? IMatchClause as matchClause ->
53+
addPatternValues matchClause.Pattern
54+
55+
| :? IBinding as binding ->
56+
Seq.iter addPatternValues binding.ParameterPatterns
57+
58+
let letBindings = LetBindingsNavigator.GetByBinding(binding)
59+
if isNotNull letBindings && letBindings.IsRecursive then
60+
addLetBindingsValues letBindings
61+
62+
| :? IAccessorDeclaration as decl ->
63+
Seq.iter addPatternValues decl.ParameterPatternsEnumerable
64+
65+
| :? IFSharpTypeDeclaration as typeDecl ->
66+
let ctorDecl = typeDecl.PrimaryConstructorDeclaration
67+
if isNotNull ctorDecl then
68+
addPatternValues ctorDecl.ParameterPatterns
69+
addSelfIdValue ctorDecl.SelfIdentifier
70+
71+
| :? IFSharpExpression as expr ->
72+
let letExpr = LetOrUseExprNavigator.GetByInExpression(expr)
73+
if isNotNull letExpr then
74+
addLetBindingsValues letExpr
75+
76+
match expr with
77+
| :? ILambdaExpr as lambdaExpr ->
78+
for pattern in lambdaExpr.PatternsEnumerable do
79+
addPatternValues pattern
80+
81+
| :? IForEachExpr as forExpr ->
82+
addPatternValues forExpr.Pattern
83+
84+
| :? IForExpr as forExpr ->
85+
addValue forExpr.Identifier
86+
87+
| _ -> ()
88+
89+
| :? IModuleMember as moduleMember ->
90+
let moduleDecl = ModuleLikeDeclarationNavigator.GetByMember(moduleMember)
91+
if isNotNull moduleDecl then
92+
let isRecursive =
93+
match moduleDecl with
94+
| :? IDeclaredModuleLikeDeclaration as moduleDecl -> moduleDecl.IsRecursive
95+
| _ -> false
96+
97+
let contextOffset =
98+
if isRecursive then moduleDecl.GetTreeEndOffset() else moduleMember.GetTreeStartOffset()
99+
100+
addMembersValues contextOffset.Offset (moduleDecl.MembersEnumerable |> Seq.cast)
101+
102+
let typeDecl = FSharpTypeDeclarationNavigator.GetByTypeMember(moduleMember.As())
103+
if isNotNull typeDecl then
104+
addMembersValues (moduleMember.GetTreeStartOffset().Offset) (typeDecl.TypeMembersEnumerable |> Seq.cast)
105+
106+
| :? ITypeBodyMemberDeclaration as typeMember ->
107+
let typeDecl = FSharpTypeDeclarationNavigator.GetByTypeMember(typeMember)
108+
if isNotNull typeDecl then
109+
addMembersValues (typeMember.GetTreeStartOffset().Offset) (typeDecl.TypeMembersEnumerable |> Seq.cast)
110+
111+
let memberDecl = typeMember.As<IMemberDeclaration>()
112+
if isNotNull memberDecl then
113+
addSelfIdValue memberDecl.SelfId
114+
Seq.iter addPatternValues memberDecl.ParameterPatterns
115+
116+
| _ -> ()
117+
118+
values

0 commit comments

Comments
 (0)