feat(FC0002): check casing of generic type arguments and subtyped object references - #502
Merged
Merged
Conversation
…ect references Walk GenericNamedDataTypeSyntax (List of [...], Dictionary of [...]) type arguments by pushing the node onto the existing explicit stack. Collect IdentifierNameSyntax nodes from SubtypedDataTypeSyntax object references and resolve via GetSymbolInfo in a new ResolveObjectReferences batch pass, grouped by (TypeName, ObjectName) to avoid cross-contamination with the identifiers list. The existing CasingMismatchCodeFix (CanonicalText + QuoteIdentifierIfNeeded) applies automatically to the new diagnostic locations. Closes #255 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…low AL 14.0 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replaces the parent-traversal cast and "\0"-separated composite group key in ResolveObjectReferences with a (TypeName, Node) tuple collected in WalkNode, grouped by the default tuple comparer like ResolveIdentifiers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Collect QualifiedNameSyntax subtypes into a dedicated batched pass. GetSymbolInfo on the qualified name resolves via the SDK's GetSymbolFromObjectReference QualifiedName case; the object name is compared against symbol.Name and namespace parts right-aligned against GetContainingNamespaceQualifiedNameWithReflection (all-TFM safe). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Closes #255
Problem
FC0002 raised no diagnostic for wrong casing inside
List of [...]/Dictionary of [...]type declarations:Two gaps in
CasingMismatchIdentifier.WalkNode:GenericNamedDataTypeSyntax(SyntaxKind.GenericDataType) was never pushed onto the walk stack, so itsTypeArgumentswere never visited —TEXT/INTERFACEinside the brackets went unchecked.SubtypedDataTypeSyntaxbranch compared only theTypeName; the object name afterRecord/Codeunit/Interface/… was never compared against the declared symbol — anywhere, including top-level declarations.Fix
GenericDataTypenodes onto the existing explicit stack (alongsideEnumDataType/LabelDataType).ChildNodes()yields only the type-argument nodes, so the outer type name is not double-reported and nested generics recurse naturally.IdentifierNameSyntaxobject references from subtyped data types and resolve them in a new batchedResolveObjectReferencespass — grouped by(TypeName, name)(separate from theidentifierslist to avoid canonical-text cross-contamination with same-named variables), oneGetSymbolInfoper group.EnumProvider.SyntaxKind.GenericDataTypemember (nameof-based; the kind exists on the netstandard2.1 floor SDK).CasingMismatchCodeFix(CanonicalText+QuoteIdentifierIfNeededWithReflection) applies to the new diagnostics unchanged — covered by newHasFixfixtures, including quote-dropping ("IMYINTERFACE"→IMyInterface) and re-quoting ("MY TABLE"→"My Table").Record MYPUBLISHER.MYEXTENSION.MYAPPDOMAIN.MYTABLE) are checked too, in a dedicatedResolveQualifiedObjectReferencespass: the object name is compared againstsymbol.Name, and each namespace part right-aligned against the declared namespace casing viaGetContainingNamespaceQualifiedNameWithReflection(all-TFM safe).Deliberately not checked: object references by numeric ID (
Record 18).Note: object-reference casing is now checked in all subtyped declarations (globals, locals, parameters, return values), not only inside generic brackets — fixing it brackets-only would have left an odd inconsistency. Severity stays Info.
Tests
HasDiagnostic/NoDiagnosticfixturesGenericDataType.al,SubtypedObjectReference.al, andNamespacedObjectReference.al(regression-first: each HasDiagnostic case failed before its analyzer change). The Interface-in-generic fixtures are skipped below AL 14.0 (AL0408).HasFix/GenericTypeArgument,HasFix/QuotedObjectReference, andHasFix/QualifiedObjectReference.ALCops.CommonandALCops.FormattingCopgreen on netstandard2.1/net8.0/net10.0.dotnet formatclean.Companion docs PR in alcops.dev follows.
🤖 Generated with Claude Code