Stop a call in an attribute value swallowing the tag's body - #51
Merged
Conversation
query name="q" cachedWithin=createTimeSpan(0,0,0,5) { ... } failed while
cachedWithin=t parsed. Not the attribute grammar: functionCall carried an
optional trailing block,
functionCall : (identifier | specialWord) LEFTPAREN argumentList RIGHTPAREN
body=compoundStatement? ;
so createTimeSpan(0,0,0,5) { echo("x"); } was read as a call with a body, taking
the block the tag needed and leaving cfmlfunctionStatement at EOF.
That label was never read. The ctx.body handling in the expression visitor
belongs to visitQualifiedFunctionCall, whose own rule keeps its body, which is
why removing this one compiles untouched and why no fixture records it. It only
ever consumed input.
The forms that do want a body still have one of their own:
cfhttp(url="a" method="GET") { } through cfmlfunctionStatement,
cfmail(to="a", from="b") { } through tagFunctionStatement.
Differential harness 8 disagreements to 7 against master, nothing newly broken.
Verified end to end -- 313 cfparser tests, ./gradlew build, CFLint's 675.
Closes #45
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GzpZFd4rnE1Yi2sVHAji35
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 #45.
query name="q" cachedWithin=t { echo("x"); } // ok query name="q" cachedWithin=createTimeSpan(0,0,0,5) { echo("x"); } // mismatched input '<EOF>'Not the parenthesis, as the issue guessed
I suspected prediction committing to the parenthesised-attribute branch. It's simpler:
functionCallcarries an optional trailing block.So
createTimeSpan(0,0,0,5) { echo("x"); }parses as a call with a body, taking the block the tag needed and leavingcfmlfunctionStatementstaring at EOF.That label was never read
The
ctx.bodyhandling inCFExpressionVisitorbelongs tovisitQualifiedFunctionCall, whose own rule keeps its body. That's why deleting this one compiles without touching a line of Java, and why no fixture's recorded tree changes. It existed only to consume input.The forms that genuinely want a body still have their own:
cfhttp(url="a" method="GET") { } // cfmlfunctionStatement cfmail(to="a", from="b") { writeOutput("x"); } // tagFunctionStatementBoth verified unchanged.
Verification
313 cfparser tests,
./gradlew buildDifferential harness 8 → 7 against master, nothing newly broken
Worth noting how I checked that: my first diff was against the No arrow function parses inside <cfset>, and the failure is silent #44 branch's results, which flagged
common: thin-arrow lambdaas newly broken. It isn't — No arrow function parses inside <cfset>, and the failure is silent #44 isn't on this branch, so that case is still failing exactly as it does on master. Re-diffed against master's actual eight. A baseline from the wrong branch is as misleading as diffing the count.CFLint 675 against a clean build
tagscript/tag_attribute_call_45.cfcfails withcfml.parsing/src/mainstashedGenerated by Claude Code