Fix hover tooltip for data structure subfields - #580
Conversation
- Add three-tier symbol lookup to hover provider:
1. Cache.referenceByOffset (offset-based, fastest path)
2. Qualified name chain walk from line text (handles name collisions,
unlimited nesting depth, reference-tracking-independent)
3. Plain findDefinition fallback
- Display full qualified name from line text (e.g. myDS.inner.field)
instead of one-level parent struct search
- Use parser.getParsedCache() instead of getDocs() so hover never
triggers a blocking re-parse; returns immediately on cold cache
- Fix word variable scope bug in procedure hover branch
- Add regression test: references_qualified_ds_subfield_hover
|
👋 A new build is available for this PR based on c4b9ba8. |
|
@bobcozzi if I put dcl-subf id doesn't work...
|
|
buzzia2001
left a comment
There was a problem hiding this comment.
Please check my 2 examples
|
Ha! Okay, I'll look at that. Funny as dcl-subf was one of my test cases, but didn't use it in a nested Data Structure as you did. |
we should be good now. have a look and then merge or let me know what else I need to look at. |
|
Does this issue still persist or can we close/merge it and move on? |
|
Behavior is still the same on my end. There have been no new extension version on since 3.0.12 so I don't think I have the latest version of the Dev Pack. |
Have you tried the code of the preview of rpg extension? |
|
How would I access the preview of rog extension? I usually just install what's available on the marketplace and I have everything set to AutoUpdate. |
|
You need the latest version of the RPGLE extension if you're not on the latest release, then you won't see the changes |
|
Hi @VertexGC you can install the vsix file in the attachments |
|
It still isn't working for me. I don't know if this makes a difference or not. Almost 100% of our Data Structures are defined with LIKEDS(typeDataStructure) which is a template that is defined in another member pulled in with a /Copy statement. Could it be having an issue finding that copy member or something? In the outline view, I can see the data structure defined as a property (with the wrench icon) but I can't drill into it to see any subfields. I got it to work in one Source Member. The subfields displayed after keying the Data Structure name and a period (.). But in another one, it doesn't work. The program (where it doesn't work) compiles, so I know the code is correct. Very strange. |
|
Correct if it does not find the /copy member, the cross reference database is not populated with that subfield information. Make sure the include member is on your library list. I'd suggest we close this out as it isn't a bug so much as a feature base on the User comment. If it turns out adding it to your library list work, and you want something else, then go ahead and open a new issue ans request it as a feature. Thanks. |
|
My library list is correct, so it should be able to find the /copy. I've had 2 source files open at the same time. It works in one and not the other. |
And excerpt of the code that works and that does not work would be helpful. Also your library list in both contexts would possibly be helpful too. |
|
I have 2 Data Structures being defined and used in the same program. One will show me subfields and the other will not. Both are defined in copybooks in the Same Source PF, different members. The source PF is in my Library list in VSCode (I'm using a profile). Example 1 - Subfields show for this one. From the Copy book... **Example 2 from the same RPG Program - Subfields are not showing ** |
|
When you said it works in one and not the other, regarding open tabs, does it always work in the same source member and not the other, or does that change depending on the order in which they are opened in the editor? |
|
See my more detailed comments above explaining that 2 different one in the same program. I gave the full definitions of the data structures in the copybooks and all of the compiler and definitions from the RPG program (service program). |
|
Sure, but the code isn't formatted. |
|
I thought I'd just send you the actual source code members and a compile listing in a ZIP file. APSSVCAGR3 is the service program. The procedure example is getServiceAgreementRouteId. ds#Service is defined in the APSSERVICE copybook and DS#ServiceAgr is defined in APSSVCAGR. |
|
Thanks I got the ZIP now. I'll open it and look at the issue sometime this week. |
|
Thanks Bob. I noticed one thing. The /Copy statements for the one that works are global in SrvPgm and the /copy statements for the other are local in the procedure, but both Data Structures are defined locally. So I moved the local /copy statements for the local one to the top and made them global, but that didn't change the behavior of the editor. |
|
I have tested your examples and in both data structures the hover text does not appear for subfields. |


Fixes #579
Summary
Hover tooltips did not appear for data structure subfields in multi-level DS (e.e., 3 or more levels deep) and only appeared when the subfield was also defined elsewhere as a stand-alone field. This PR fixes the lookup logic in the hover provider and improves hover performance.
Root Cause
The hover provider used only a word-based lookup (
getWordRangeAtPosition→findDefinition).findDefinitionroutes throughCache.findSubfields()which deliberately skips QUALIFIED data structures — so subfields likedirty.Fruitwere never found.Changes
extension/server/src/providers/hover.tsThree-tier symbol lookup (single backwards line-text walk shared between all tiers):
Cache.referenceByOffset): fastest path, works whencollectReferenceshas runfindDefinition(parts[0])thensubItems.findat each level. Reference-tracking-independent, handles name collisions (same name as standalone variable and subfield), supports unlimited nesting depth (outerDS.innerDS.subfield)findDefinition(word))Full qualified name in display: Extracts the complete dot-chain from line text (e.g.
multiTear.stuff.count) and uses it verbatim as the symbol display name, replacing the previous one-level parent struct search.Performance: Use
parser.getParsedCache()instead ofparser.getDocs()so hover never triggers a blocking re-parse. Cold cache returns immediately (no tooltip, no freeze); warm cache returns instantly.Bug fix:
wordwas declared insideif (!symbol)block scope but referenced outside it in the procedure branch — changed toword || ''.tests/suite/references.test.tsAdded
references_qualified_ds_subfield_hover— verifies thatCache.referenceByOffsetreturns the correctsubitemDeclaration at qualified subfield usage offsets, distinguishing it correctly from a standalone variable with the same name.