Skip to content

Accept inline component definitions - #55

Merged
ghedwards merged 1 commit into
masterfrom
claude/fix-inline-component-49
Aug 13, 2026
Merged

Accept inline component definitions#55
ghedwards merged 1 commit into
masterfrom
claude/fix-inline-component-49

Conversation

@ghedwards

Copy link
Copy Markdown

Closes #49.

var msal = new component javaSettings='{"maven":["com.microsoft.azure:msal4j:1.23.1"]}' {
	function buildApp() { ... }
};

newComponentExpression required a path and a parenthesised argument list. The inline form has neither.

Grammar

The new alternative is NEW componentDeclaration — reusing the existing rule rather than restating its shape, so attributes, directives and members behave exactly as they do in a named component.

AST

CFAnonymousComponentExpression follows CFAnonymousFunctionExpression: a declaration statement hanging off an expression. The issue pointed at that precedent and it holds up — same problem, already solved once for function(){}.

The check that matters isn't the parse, it's the walk:

CFAnonymousComponentExpression
  CFCompDeclStatement
    CFFuncDeclStatement name=buildApp

Members reachable via decomposeScript(). Per CLAUDE.md, a green parse would have proved nothing here — this is exactly where #16 and #18 went wrong.

It regressed an existing fixture, and that was the interesting part

Adding the alternative broke parsing/cached_cf573.cfc, whose function carries cachedwithin=createTimeSpan(1,0,0,0) before its body.

That's the latent bug from #45 one rule over: simpleFunctionCall also had an optional trailing block, so the call swallowed the function's body. My alternative didn't create that — it only changed which way prediction fell.

Removing that body makes the fixture pass with its recorded tree untouched. I deliberately did not regenerate it: an unchanged expected file is the evidence that the removal restores correct behaviour rather than rationalising a new one. As with functionCall in #45, no visitor reads it — the ctx.body handling belongs to visitQualifiedFunctionCall, whose own rule keeps its own.

Worth noting for review order: #45 removes the same thing from functionCall. Different lines, so no textual conflict, but they're two halves of one problem.

Verification

  • 313 cfparser tests, ./gradlew build, no expected file regenerated
  • Differential harness 8 → 7, nothing newly broken
  • CFLint 675 against a clean build
  • components/inline_component_49.cfc fails with cfml.parsing/src/main stashed

Generated by Claude Code

`new component { ... }` declares and instantiates in one expression.
newComponentExpression required a path and a parenthesised argument list, and
the inline form has neither.

The new alternative is `NEW componentDeclaration`, reusing the existing rule
rather than restating its shape, so attributes, directives and members behave
exactly as they do in a named component.

CFAnonymousComponentExpression follows CFAnonymousFunctionExpression: a
declaration statement hanging off an expression, which is the same problem this
repo already solved once for function(){}. A walk reaches the inline
component's members through decomposeScript --

  CFAnonymousComponentExpression
    CFCompDeclStatement
      CFFuncDeclStatement name=buildApp

which is the part that matters; a green parse would have proved nothing.

Adding the alternative regressed parsing/cached_cf573.cfc, whose function
carries `cachedwithin=createTimeSpan(1,0,0,0)` before its body. That is the
latent bug in #45 one rule over: simpleFunctionCall also had an optional
trailing block, so the call swallowed the function's body. The new alternative
only changed which way prediction fell. Removing that body restores the
fixture's recorded tree untouched, which is the evidence the removal is right
rather than convenient -- as with functionCall, no visitor reads it; the ctx.body
handling belongs to visitQualifiedFunctionCall, whose own rule keeps its own.

Differential harness 8 disagreements to 7, nothing newly broken. Verified end to
end -- 313 cfparser tests, ./gradlew build, CFLint's 675.

Closes #49

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GzpZFd4rnE1Yi2sVHAji35
@ghedwards
ghedwards merged commit dd7b9f1 into master Aug 13, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

new component { ... } — inline component definitions are not supported

2 participants