Fix/colon prefix dot access hover - #386
Open
geircodes wants to merge 2 commits into
Open
Conversation
Clarion allows a literal ':' inside an identifier (e.g. GLOB:Thing), a naming convention for globals that is unrelated to GROUP/QUEUE PRE(...) prefixing. Hovering a member reached via dot access on such a variable (GLOB:Thing.Foo) silently returned no hover for method calls, while property access happened to still show something via an unrelated fallback. Two independent spots dropped the colon-prefixed segment before resolving the receiver's type: - TokenHelper.getWordRangeAtPosition's backward scan (building the hover "word") accepted ':' when scanning forward for the word under the cursor, but not when scanning backward to include the prefix before a dot - producing a mismatched, truncated word for the dotted-access case. - StructureFieldResolver.resolveFieldAccess's structureNameMatch regex (`\w+`) also excludes ':', independently truncating the receiver name before it's passed to variable-type resolution. Either bug alone drops "GLOB:Thing" to "Thing", which then fails to match the actual declaration, so the receiver's type never resolves and the member lookup returns null. This is why it looked property-only: a property access can still surface something via an unrelated bare-name fallback elsewhere in the resolution ladder, but a method call has no such fallback and simply produced no hover. Added a regression test with a synthetic CLASS + colon-prefixed global covering both a method call and a property access; confirmed both fail without the fix and pass with it.
…d by the colon-prefix fix Confirms widening the backward word-scan / structureNameMatch regex to accept ':' does not change resolution for GROUP PRE(...) prefixed field access via dot notation (Config.Nested.Setting has no ':' in it at all, so the widened regexes never apply), even when it coexists in the same file as the colon-prefixed global dot-access chain the previous commit fixes. While building this test, found and confirmed a separate, pre-existing, unrelated bug: a procedure implementation's computed body range (`finishesAt`) can over-reach past its own END into the very next declaration when that declaration is followed later by another PROCEDURE. Reproduced with a plain non-colon variable in the identical shape to confirm it has nothing to do with colon handling - not fixed here, out of scope for this PR, left as a note for whoever picks it up next.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Clarion allows a literal
:inside an identifier — a common naming convention for globals (GLOB:Thing), separate from GROUP/QUEUEPRE(...)prefixing. Hovering a method reached via dot access on such a variable produced no hover at all; hovering a property the same way happened to still show something, which made this look property-safe / method-only at first. It isn't — both are broken the same way, one just has a lucky fallback masking it.Root cause
Two independent spots drop the colon-prefixed segment before the receiver's type ever gets resolved:
TokenHelper.getWordRangeAtPosition— the forward scan (finding the word under the cursor) explicitly allows:(includeColons), but the backward scana few lines below it (walking left to include the prefix before a dot, e.g. forGLOB:Config.DoWork) only allows[A-Za-z0-9_]. For a colon-containing prefix, this produces the wrong compound hover "word" (Config.DoWorkinstead ofGLOB:Config.DoWork).StructureFieldResolver.resolveFieldAccess—structureNameMatch = beforeDot.match(/(\w+)\s*$/)has the same gap:\wexcludes:, so the receiver name extracted for variable-type resolution is truncated toConfig, which doesn'tmatch the actual declaration
GLOB:Config.resolveVariableTypethen fails and the whole "look up this member in its class" path never runs.Either bug alone is enough to break it. Why properties still "worked": a property access can incidentally be caught by a later, unrelated bare-name fallback further down the hover resolution ladder (a plain "does any symbol have this exact name
anywhere reachable" search) — which finds the property by coincidence, not because the receiver's type was correctly resolved. A method call has no equivalent fallback, so it just returns null. That's also why this could silently point at the wrong declaration if two unrelated classes happened to declare a same-named property — the accidental match isn't scoped to the receiver's real type at all.
Fixed both spots to allow
:consistently, matching how the rest of the file already treats colon-containing identifiers.Possibly related earlier work
Not a regression of either of these as far as I can tell — cited for anyone triaging future colon/prefix hover reports, since this is the third or so bug in this general area:
CHANGELOG-full.md) — "PREFIX and Structure Field AccessImprovements" added dedicated support for
LOC:MyVar/MyGroup.MyVar/ bareaccess for GROUP
PRE(...)fields, plus a companion "word extraction for dotnotation" fix in this same
getWordRangeAtPositionarea. That work coversstructure-PRE prefixes specifically; a colon that's simply part of a global's own
name (no
PRE(...)involved) falls through the same code but isn't a PRE-prefixcase, so it wasn't covered.
BRW1::View:Browse-style labels) is the same symptom family (colon droppedduring identifier handling) but in the Go to Definition label-search path, not
hover's dot-access chain.
Might be worth a "colon-in-identifiers" sweep across the remaining resolvers at some point, since this pattern (
\w+-style regex, or a hand-rolled word-character check) recurs independently in at least three unrelated files now.Test plan
npx tsc -b— clean compileColonPrefixedGlobalDotAccessHover.test.ts— synthetic CLASS + colon-prefixed global reference, one method-call case and one property-access case; both fail without the fix (confirmed by temporarily reverting it) and pass with itColonAndPreDotAccessInteraction.test.ts— adversarial check that widening both regexes to accept:doesn't regress the pre-existing GROUPPRE(...)dot-access case (Config.Nested.Setting, no:anywhere in that chain) when it coexists in the same file as the colon-prefixed global fix above. Also confirmed by reasoning over the code: multi-segment chains (2+ dots) never hit either changed regex at all —ChainedPropertyResolveralready splits on.and passes the un-truncated segment straight intoresolveVariableType, both before and after this PR.HoverProvider.provideHoverharness against a real-world.clwfile with a colon-prefixed global class instance, confirmed the method-call hover now resolves (including correctly picking the right overload/class when another unrelated class declares a same-named method) and the property hover now goes through the real class-member path instead of the coincidental fallback🤖 Generated with Claude Code