Repository navigation
Conversation
…s check The legacy dotted form alias.TypeName is a heuristic reread of ident.UppercaseField member access, and it fired on every such access: properties.Status on a properties: Map<String, Any> field drew an error-severity undefinedImportedAlias in a module with zero use declarations (juxt#97). QRefs minted by the dotted heuristic now carry a dotted flag, and the unknown-alias error stands down when the qualifier is a value name the module binds anywhere: block item names (entity / external-entity / value fields, given bindings, config parameters, surface projections), variant field declarations, default declaration names, lets, trigger parameters, surface context bindings, lambda and for bindings, top-level invariant bodies included. A dotted qualifier bound nowhere still errors, slash-form references are never exempt, and a deferred declaration's dotted path — a code location, not a value — keeps its error even when the module binds a value name spelled the same.
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.
Fixes #97.
Bug
The reference checker rereads
ident.UppercaseFieldmember access as the legacy dotted import formalias.TypeName. The reread is a heuristic added for usage crediting (v3.2.3), where over-inclusion was harmless; since 3.5.3's unified alias validation it also feedscheck_undefined_import_aliases, where over-inclusion is an error-severity false positive:errors twice with
allium.reference.undefinedImportedAlias— "Reference 'properties/Status' uses unknown import alias 'properties'" — in a module with zerousedeclarations, naming an alias the author never wrote. The parser disagrees with the diagnosis:allium parseyields plainMemberAccessfor this shape (a realp/Nameis a distinctQualifiedNamenode), and the member's capitalisation alone flips valid spec text to an error (properties.status.nameis silent). There is no alternative syntax for a capitalisedMapkey —properties["Status"]is not grammar.Fix
QRefs minted by the dotted heuristic now carry a
dotted: boolflag (documented in the same style as thecollectionflag's #82 exemption). The unknown-alias error stands down for a dotted reference whose qualifier is a locally-bound value name — an entity/external-entity/value field, alet, agivenbinding, a rule trigger parameter, a surfacecontext/facingbinding, a config parameter, adefaultdeclaration's name, avariantfield, a surfacename:item, a lambda orforbinding — top-levelinvariantbodies included (collect_local_value_names, a deliberate module-wide over-approximation: its one consumer only suppresses an error, so over-inclusion fails safe, while under-inclusion is the false positive being fixed).Everything else is unchanged:
alias.TypeNameform with a missinguse, and it stays caught;core.Missingstill warnsunknownName);p/Namewith nousestill errors — check: a suppressedallium.use.unresolvedPathsilently disables all name checking through that alias (exit 0 on arbitrary dangling references) #87's case C);deferreddeclaration's dotted path names a code location, never member access, so refs minted from it are neverdottedand never exempt;collect_qualified_referencesetc.) are untouched.Tests
New integration file
crates/allium/tests/dotted_member_access.rs(harness mirrorscross_module_lifecycle.rs), 12 tests: the headline repro draws zero reference diagnostics; lowercase-member control; OptionalAccess (properties?.Status), trigger-param/let, top-levelinvariant-body,variant-field,default-name and surface-binding qualifiers all exempt; unbound dotted qualifier still errors; a dotteddeferredpath is NEVER exempt (a dangling legacy deferred reference keeps its error even when the module binds a value name spelled the same); slash-form unknown alias still errors (#87's case C); dotted-with-alias still name-checked. Every exemption test is red on main; the guards pass on both sides. Behaviour spec updated (three new rules + one addedrequires:onUndeclaredImportAliasIsDiagnosedAtEveryReferenceSite); CHANGELOG entry under Unreleased. Full workspace suite green; clippy warning set byte-identical to main; the repo's owndocs/project/specsdiagnostics are byte-identical before/after.Real-world impact
Any spec that models externally-named data can hit this: the keys of a
Map<String, Any>field frequently come from an outside system that capitalises them (JSON API fields, HTTP header names, the page properties of a SaaS tool). The natural read —properties.Status.status.name— currently draws an error-severity diagnostic naming an import alias the author never wrote, in a module that may declare no imports at all, and no spelling of the access avoids it (properties["Status"]is not grammar). The available workarounds both document the checker instead of the domain: mute an error-severity code line by line, or restructure the spec so the capitalised name only ever appears as a string literal (e.g. route the read through adeferredlookup function).Supporting evidence from a private ~190-spec corpus we maintain: one such derived field reddened the whole-tree gate with two errors, and a full-corpus diagnostic diff with this fix shows exactly those two disappearing and nothing else changing at any severity. This change only removes diagnostics; no previously green gate turns red.
Note: this PR and the surface-offering one both touch
analysis.rs, the check behaviour spec, and the CHANGELOG - whichever merges second needs a trivial union rebase; happy to rebase promptly.