Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion cfml.parsing/src/main/antlr4/cfml/CFSCRIPTParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,6 @@ functionCall
;
simpleFunctionCall
:(identifier | specialWord) LEFTPAREN argumentList RIGHTPAREN
body=compoundStatement?
;
qualifiedFunctionCall
:(identifier | reservedWord) LEFTPAREN argumentList RIGHTPAREN
Expand Down Expand Up @@ -783,8 +782,12 @@ implicitStructKeyExpression
| reservedWord
;

// `new component { ... }` defines and instantiates in one expression. The body is an
// ordinary componentDeclaration, reused rather than restated so attributes, directives
// and members all behave the same as in a named component.
newComponentExpression
: NEW componentPath LEFTPAREN argumentList RIGHTPAREN
| NEW componentDeclaration
;

// Lucee types the path being instantiated: new java:java.io.File(p), new cfml:foo.Bar().
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package cfml.parsing.cfscript;

import java.util.List;

import org.antlr.v4.runtime.Token;

import cfml.parsing.cfscript.script.CFCompDeclStatement;
import cfml.parsing.cfscript.script.CFScriptStatement;
import cfml.parsing.util.ArrayBuilder;

/**
* An inline component: <code>new component javaSettings='...' { ... }</code>, which declares and
* instantiates in one expression.
*
* Modelled the way {@link CFAnonymousFunctionExpression} models <code>function(){}</code> -- a
* declaration statement hanging off an expression -- so a walk that already descends into an
* anonymous function reaches an inline component's members the same way.
*/
public class CFAnonymousComponentExpression extends CFExpression {

private static final long serialVersionUID = 1L;

private CFCompDeclStatement componentDeclaration;

public CFAnonymousComponentExpression(Token _t, CFCompDeclStatement _componentDeclaration) {
super(_t);
componentDeclaration = _componentDeclaration;
if (componentDeclaration != null) {
componentDeclaration.setParent(this);
}
}

@Override
public byte getType() {
return CFExpression.NESTED;
}

public CFCompDeclStatement getComponentDeclaration() {
return componentDeclaration;
}

@Override
public String Decompile(int indent) {
return "new " + componentDeclaration.Decompile(0);
}

@Override
public List<CFExpression> decomposeExpression() {
return ArrayBuilder.createCFExpression();
}

@Override
public List<CFScriptStatement> decomposeScript() {
return ArrayBuilder.createCFScriptStatement(componentDeclaration);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import cfml.CFSCRIPTParser.CfmlFunctionContext;
import cfml.CFSCRIPTParser.CompareExpressionContext;
import cfml.CFSCRIPTParser.ComponentAttributeContext;
import cfml.CFSCRIPTParser.ComponentDeclarationContext;
import cfml.CFSCRIPTParser.ComponentGutsContext;
import cfml.CFSCRIPTParser.ComponentPathContext;
import cfml.CFSCRIPTParser.ConditionContext;
Expand Down Expand Up @@ -57,6 +58,7 @@
import cfml.CFSCRIPTParser.UnaryExpressionContext;
import cfml.CFSCRIPTParserBaseVisitor;
import cfml.parsing.cfscript.ArgumentsVector;
import cfml.parsing.cfscript.CFAnonymousComponentExpression;
import cfml.parsing.cfscript.CFAnonymousFunctionExpression;
import cfml.parsing.cfscript.CFArrayExpression;
import cfml.parsing.cfscript.CFAssignmentExpression;
Expand All @@ -78,6 +80,7 @@
import cfml.parsing.cfscript.CFTernaryExpression;
import cfml.parsing.cfscript.CFUnaryExpression;
import cfml.parsing.cfscript.CFVarDeclExpression;
import cfml.parsing.cfscript.script.CFCompDeclStatement;
import cfml.parsing.cfscript.script.CFFuncDeclStatement;
import cfml.parsing.cfscript.script.CFReturnStatement;

Expand Down Expand Up @@ -429,6 +432,13 @@ private CFIdentifier makeIdentifier(CFExpression visit) {

@Override
public CFExpression visitNewComponentExpression(NewComponentExpressionContext ctx) {
if (ctx.componentDeclaration() != null) {
// `new component { ... }` -- the declaration is built by the statement visitor, the way
// an anonymous function's is, and wrapped so it can sit in an expression.
CFCompDeclStatement declaration = (CFCompDeclStatement) getCFScriptStatementVisitor()
.visitComponentDeclaration(ctx.componentDeclaration());
return new CFAnonymousComponentExpression(ctx.NEW().getSymbol(), declaration);
}
ArgumentsVector args = new ArgumentsVector();
if (ctx.getChildCount() > 4) {
for (ArgumentContext argCtx : ctx.argumentList().argument()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
component {
function connect() {
// Declares and instantiates in one expression -- the shape Lucee uses to pull a
// Maven dependency in via javaSettings.
var msal = new component javaSettings='{"maven":["com.microsoft.azure:msal4j:1.23.1"]}' {
function buildApp() {
return 1;
}
};
// Without attributes, and the ordinary path forms alongside it.
var bare = new component { function f() { return 2; } };
var named = new models.User();
var javaFile = new java:java.io.File(path);
return msal;
}
}
Loading
Loading