Author: nbubna
Date: Fri Jan 16 14:13:10 2009
New Revision: 735156
URL: http://svn.apache.org/viewvc?rev=735156&view=rev
Log:
VELOCITY-666 add support for calling macros with a body (thanks to Jarkko
Viinamki)
Modified:
velocity/engine/trunk/src/changes/changes.xml
velocity/engine/trunk/src/java/org/apache/velocity/context/ProxyVMContext.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/defaults/velocity.properties
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/RuntimeMacro.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.jj
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/ParserTokenManager.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTDirective.java
velocity/engine/trunk/src/parser/Parser.jjt
Modified: velocity/engine/trunk/src/changes/changes.xml
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/changes/changes.xml?rev=735156&r1=735155&r2=735156&view=diff
==============================================================================
--- velocity/engine/trunk/src/changes/changes.xml (original)
+++ velocity/engine/trunk/src/changes/changes.xml Fri Jan 16 14:13:10 2009
@@ -27,6 +27,15 @@
<body>
<release version="1.7" date="In Subversion">
+
+ <action type="add" dev="byron" issue="VELOCITY-666" due-to="Jarkko
Viinamaki">
+ Add support for calling velocimacros with body content by prefixing
the macro
+ name with @.
+ (e.g. #macro( bold )<strong>$bodyContent</strong>#end #...@bold()any
valid VTL here#end)
+ The $bodyContent reference may be renamed via a
velocimacro.body.reference
+ setting in your velocity.properties.
+ </action>
+
<action type="fix" dev="nbubna" issue="VELOCITY-661" due-to="Jarkko
Viinamaki">
Added #[[this is included in output but not parsed]]# syntax to replace
and deprecate the much more limited #literal directive
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/context/ProxyVMContext.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/context/ProxyVMContext.java?rev=735156&r1=735155&r2=735156&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/context/ProxyVMContext.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/context/ProxyVMContext.java
Fri Jan 16 14:13:10 2009
@@ -32,6 +32,7 @@
import org.apache.velocity.runtime.parser.ParserTreeConstants;
import org.apache.velocity.runtime.parser.node.ASTReference;
import org.apache.velocity.runtime.parser.node.Node;
+import org.apache.velocity.runtime.parser.node.ASTBlock;
import org.apache.velocity.runtime.resource.Resource;
import org.apache.velocity.util.introspection.IntrospectionCacheData;
@@ -56,7 +57,7 @@
Map vmproxyhash = new HashMap(8, 0.8f);
/** container for any local or constant macro arguments. Size must be
power of 2. */
- Map localcontext = new HashMap(8, 0.8f);;
+ Map localcontext = new HashMap(8, 0.8f);
/** support for local context scope feature, where all references are
local */
private boolean localContextScope;
@@ -123,6 +124,7 @@
case ParserTreeConstants.JJTMAP:
case ParserTreeConstants.JJTSTRINGLITERAL:
case ParserTreeConstants.JJTTEXT:
+ case ParserTreeConstants.JJTBLOCK:
return (false);
default:
return (true);
@@ -218,6 +220,28 @@
return obj;
}
}
+ else if (type == ParserTreeConstants.JJTBLOCK)
+ {
+ // this happens for #...@somemacro($arg1 $arg2) bodyAST #end
calls
+ try
+ {
+ // astNode is actually BlockMacro.BlockMacroContainer
which contains a Writer internally although
+ // we seem to pass null here
+ astNode.render(innerContext, null);
+ // return an empty string because the Node already
rendered all content
+ return "";
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ String msg = "ProxyVMContext.get() : error rendering
reference";
+ rsvc.getLog().error(msg, e);
+ throw new VelocityException(msg, e);
+ }
+ }
else if (type == ParserTreeConstants.JJTTEXT)
{
// this really shouldn't happen. text is just a throwaway arg
for #foreach()
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java?rev=735156&r1=735155&r2=735156&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java
Fri Jan 16 14:13:10 2009
@@ -164,7 +164,6 @@
*/
String EVALUATE_CONTEXT_CLASS = "directive.evaluate.context.class";
-
/*
* ----------------------------------------------------------------------
* R E S O U R C E M A N A G E R C O N F I G U R A T I O N
@@ -280,6 +279,12 @@
* @since 1.6
*/
String VM_MAX_DEPTH = "velocimacro.max.depth";
+
+ /**
+ * Defines name of the reference that can be used to get the AST block
passed to block marco call.
+ * @since 1.7
+ */
+ String VM_BODY_REFERENCE = "velocimacro.body.reference";
/*
* ----------------------------------------------------------------------
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/defaults/velocity.properties
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/defaults/velocity.properties?rev=735156&r1=735155&r2=735156&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/defaults/velocity.properties
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/defaults/velocity.properties
Fri Jan 16 14:13:10 2009
@@ -127,6 +127,14 @@
velocimacro.arguments.strict = false
# ----------------------------------------------------------------------------
+# VELOCIMACRO BODY REFERENCE
+# ----------------------------------------------------------------------------
+# Defines name of the reference that can be used to render the AST block
passed to
+# block macro call as an argument inside a macro.
+# ----------------------------------------------------------------------------
+velocimacro.body.reference=bodyContent
+
+# ----------------------------------------------------------------------------
# STRICT REFERENCE MODE
# ----------------------------------------------------------------------------
# if true, will throw a MethodInvocationException for references
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/RuntimeMacro.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/RuntimeMacro.java?rev=735156&r1=735155&r2=735156&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/RuntimeMacro.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/RuntimeMacro.java
Fri Jan 16 14:13:10 2009
@@ -201,7 +201,7 @@
* @param context
* @param writer
* @param node
- * @return true if the rendering is successfull
+ * @return true if the rendering is successful
* @throws IOException
* @throws ResourceNotFoundException
* @throws ParseErrorException
@@ -212,6 +212,27 @@
throws IOException, ResourceNotFoundException,
ParseErrorException, MethodInvocationException
{
+ return render(context, writer, node, null);
+ }
+
+ /**
+ * This method is used with BlockMacro when we want to render a macro with
a body AST.
+ *
+ * @param context
+ * @param writer
+ * @param node
+ * @param body AST block that was enclosed in the macro body.
+ * @return true if the rendering is successful
+ * @throws IOException
+ * @throws ResourceNotFoundException
+ * @throws ParseErrorException
+ * @throws MethodInvocationException
+ */
+ public boolean render(InternalContextAdapter context, Writer writer,
+ Node node, Node body)
+ throws IOException, ResourceNotFoundException,
+ ParseErrorException, MethodInvocationException
+ {
VelocimacroProxy vmProxy = null;
String renderingTemplate = context.getCurrentTemplateName();
@@ -271,7 +292,7 @@
try
{
- return vmProxy.render(context, writer, node);
+ return vmProxy.render(context, writer, node, body);
}
catch (RuntimeException e)
{
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java?rev=735156&r1=735155&r2=735156&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java
Fri Jan 16 14:13:10 2009
@@ -55,6 +55,7 @@
private boolean strictArguments;
private boolean localContextScope = false;
private int maxCallDepth;
+ private String bodyReference;
/**
* Return name of this Velocimacro.
@@ -127,6 +128,12 @@
return numMacroArgs;
}
+ public boolean render(InternalContextAdapter context, Writer writer, Node
node)
+ throws IOException, MethodInvocationException,
MacroOverflowException
+ {
+ return render(context, writer, node, null);
+ }
+
/**
* Renders the macro using the context.
*
@@ -138,7 +145,7 @@
* @throws MethodInvocationException
* @throws MacroOverflowException
*/
- public boolean render(InternalContextAdapter context, Writer writer, Node
node)
+ public boolean render(InternalContextAdapter context, Writer writer, Node
node, Node body)
throws IOException, MethodInvocationException,
MacroOverflowException
{
// wrap the current context and add the macro arguments
@@ -153,8 +160,6 @@
// the 0th element is the macro name
for (int i = 1; i < argArray.length && i <= callArguments; i++)
{
- Node macroCallArgument = node.jjtGetChild(i - 1);
-
/*
* literalArgArray[i] is needed for "render literal if null"
functionality.
* The value is used in ASTReference render-method.
@@ -164,9 +169,15 @@
* This makes VMReferenceMungeVisitor obsolete and it would
not work anyway
* when the macro AST is shared
*/
- vmc.addVMProxyArg(context, argArray[i], literalArgArray[i],
macroCallArgument);
+ vmc.addVMProxyArg(context, argArray[i], literalArgArray[i],
node.jjtGetChild(i - 1));
}
}
+
+ // if this macro was invoked by a call directive, we might have a body
AST here. Put it into context.
+ if( body != null )
+ {
+ vmc.addVMProxyArg(context, bodyReference, "", body);
+ }
/*
* check that we aren't already at the max call depth
@@ -242,6 +253,9 @@
// get the macro call depth limit
maxCallDepth = rsvc.getInt(RuntimeConstants.VM_MAX_DEPTH);
+
+ // get name of the reference that refers to AST block passed to block
macro call
+ bodyReference = rsvc.getString(RuntimeConstants.VM_BODY_REFERENCE,
"bodyContent");
}
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.java?rev=735156&r1=735155&r2=735156&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.java
Fri Jan 16 14:13:10 2009
@@ -740,17 +740,24 @@
if ( d == null)
{
- /*
- * if null, then not a real directive, but maybe a Velocimacro
- */
-
- isVM = rsvc.isVelocimacro(directiveName, currentTemplateName);
-
- /*
- * Currently, all VMs are LINE directives
- */
-
- directiveType = Directive.LINE;
+ if( directiveName.startsWith("@") )
+ {
+ // block macro call of type: #...@foobar($arg1 $arg2) astBody
#end
+ directiveType = Directive.BLOCK;
+ }
+ else
+ {
+ /*
+ * if null, then not a real directive, but maybe a Velocimacro
+ */
+
+ isVM = rsvc.isVelocimacro(directiveName, currentTemplateName);
+
+ /*
+ * Currently, all VMs are LINE directives
+ */
+ directiveType = Directive.LINE;
+ }
}
else
{
@@ -2743,21 +2750,6 @@
finally { jj_save(11, xla); }
}
- private boolean jj_3_8() {
- if (jj_3R_33()) return true;
- return false;
- }
-
- private boolean jj_3R_40() {
- if (jj_scan_token(INTEGER_LITERAL)) return true;
- return false;
- }
-
- private boolean jj_3R_74() {
- if (jj_3R_73()) return true;
- return false;
- }
-
private boolean jj_3R_97() {
if (jj_scan_token(COMMA)) return true;
if (jj_3R_29()) return true;
@@ -2780,13 +2772,13 @@
return false;
}
- private boolean jj_3R_67() {
- if (jj_scan_token(FLOATING_POINT_LITERAL)) return true;
+ private boolean jj_3R_71() {
+ if (jj_scan_token(FALSE)) return true;
return false;
}
- private boolean jj_3R_71() {
- if (jj_scan_token(FALSE)) return true;
+ private boolean jj_3R_40() {
+ if (jj_scan_token(INTEGER_LITERAL)) return true;
return false;
}
@@ -2840,6 +2832,11 @@
return false;
}
+ private boolean jj_3R_67() {
+ if (jj_scan_token(FLOATING_POINT_LITERAL)) return true;
+ return false;
+ }
+
private boolean jj_3R_84() {
if (jj_3R_68()) return true;
return false;
@@ -3068,13 +3065,13 @@
return false;
}
- private boolean jj_3_2() {
- if (jj_scan_token(DOUBLE_ESCAPE)) return true;
+ private boolean jj_3R_51() {
+ if (jj_3R_65()) return true;
return false;
}
- private boolean jj_3R_51() {
- if (jj_3R_65()) return true;
+ private boolean jj_3_2() {
+ if (jj_scan_token(DOUBLE_ESCAPE)) return true;
return false;
}
@@ -3185,13 +3182,13 @@
return false;
}
- private boolean jj_3R_26() {
- if (jj_3R_40()) return true;
+ private boolean jj_3R_98() {
+ if (jj_3R_24()) return true;
return false;
}
- private boolean jj_3R_98() {
- if (jj_3R_24()) return true;
+ private boolean jj_3R_26() {
+ if (jj_3R_40()) return true;
return false;
}
@@ -3241,11 +3238,6 @@
return false;
}
- private boolean jj_3_1() {
- if (jj_3R_24()) return true;
- return false;
- }
-
private boolean jj_3R_69() {
if (jj_scan_token(LBRACKET)) return true;
Token xsp;
@@ -3255,6 +3247,11 @@
return false;
}
+ private boolean jj_3_1() {
+ if (jj_3R_24()) return true;
+ return false;
+ }
+
private boolean jj_3R_77() {
Token xsp;
xsp = jj_scanpos;
@@ -3274,11 +3271,6 @@
return false;
}
- private boolean jj_3R_50() {
- if (jj_3R_71()) return true;
- return false;
- }
-
private boolean jj_3R_68() {
if (jj_scan_token(LEFT_CURLEY)) return true;
Token xsp;
@@ -3295,6 +3287,11 @@
return false;
}
+ private boolean jj_3R_50() {
+ if (jj_3R_71()) return true;
+ return false;
+ }
+
private boolean jj_3R_49() {
if (jj_3R_70()) return true;
return false;
@@ -3331,23 +3328,36 @@
return false;
}
+ private boolean jj_3R_90() {
+ if (jj_3R_73()) return true;
+ return false;
+ }
+
private boolean jj_3R_45() {
if (jj_3R_66()) return true;
return false;
}
- private boolean jj_3R_90() {
+ private boolean jj_3R_89() {
if (jj_3R_73()) return true;
return false;
}
+ private boolean jj_3R_37() {
+ if (jj_3R_40()) return true;
+ return false;
+ }
+
private boolean jj_3R_44() {
if (jj_3R_40()) return true;
return false;
}
- private boolean jj_3R_89() {
- if (jj_3R_73()) return true;
+ private boolean jj_3R_27() {
+ if (jj_scan_token(COMMA)) return true;
+ Token xsp;
+ xsp = jj_scanpos;
+ if (jj_scan_token(31)) jj_scanpos = xsp;
return false;
}
@@ -3356,8 +3366,8 @@
return false;
}
- private boolean jj_3R_37() {
- if (jj_3R_40()) return true;
+ private boolean jj_3R_34() {
+ if (jj_3R_60()) return true;
return false;
}
@@ -3366,11 +3376,8 @@
return false;
}
- private boolean jj_3R_27() {
- if (jj_scan_token(COMMA)) return true;
- Token xsp;
- xsp = jj_scanpos;
- if (jj_scan_token(31)) jj_scanpos = xsp;
+ private boolean jj_3R_36() {
+ if (jj_3R_24()) return true;
return false;
}
@@ -3413,16 +3420,6 @@
return false;
}
- private boolean jj_3R_34() {
- if (jj_3R_60()) return true;
- return false;
- }
-
- private boolean jj_3R_36() {
- if (jj_3R_24()) return true;
- return false;
- }
-
private boolean jj_3R_32() {
if (jj_3R_60()) return true;
return false;
@@ -3453,13 +3450,23 @@
return false;
}
- private boolean jj_3R_65() {
- if (jj_scan_token(STRING_LITERAL)) return true;
+ private boolean jj_3R_31() {
+ if (jj_3R_40()) return true;
return false;
}
- private boolean jj_3R_31() {
- if (jj_3R_40()) return true;
+ private boolean jj_3_8() {
+ if (jj_3R_33()) return true;
+ return false;
+ }
+
+ private boolean jj_3R_74() {
+ if (jj_3R_73()) return true;
+ return false;
+ }
+
+ private boolean jj_3R_65() {
+ if (jj_scan_token(STRING_LITERAL)) return true;
return false;
}
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.jj
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.jj?rev=735156&r1=735155&r2=735156&view=diff
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.jj
(original)
+++ velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.jj
Fri Jan 16 14:13:10 2009
@@ -1094,8 +1094,8 @@
TOKEN:
{
<#LETTER: [ "a"-"z", "A" - "Z" ] >
-| <#DIRECTIVE_CHAR: [ "a"-"z", "A"-"Z", "0"-"9", "_" ] >
-| <WORD: ( <LETTER> | ["_"]) (<DIRECTIVE_CHAR>)* >
+| <#DIRECTIVE_CHAR: [ "a"-"z", "A"-"Z", "0"-"9", "_", "@" ] >
+| <WORD: ( <LETTER> | ["_"] | ["@"]) (<DIRECTIVE_CHAR>)* >
| <BRACKETED_WORD: "{" ( <LETTER> | ["_"]) (<DIRECTIVE_CHAR>)* "}" >
}
@@ -1618,17 +1618,24 @@
if ( d == null)
{
- /*
- * if null, then not a real directive, but maybe a Velocimacro
- */
-
- isVM = rsvc.isVelocimacro(directiveName, currentTemplateName);
-
- /*
- * Currently, all VMs are LINE directives
- */
-
- directiveType = Directive.LINE;
+ if( directiveName.startsWith("@") )
+ {
+ // block macro call of type: #...@foobar($arg1 $arg2) astBody
#end
+ directiveType = Directive.BLOCK;
+ }
+ else
+ {
+ /*
+ * if null, then not a real directive, but maybe a Velocimacro
+ */
+
+ isVM = rsvc.isVelocimacro(directiveName, currentTemplateName);
+
+ /*
+ * Currently, all VMs are LINE directives
+ */
+ directiveType = Directive.LINE;
+ }
}
else
{
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/ParserTokenManager.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/ParserTokenManager.java?rev=735156&r1=735155&r2=735156&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/ParserTokenManager.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/ParserTokenManager.java
Fri Jan 16 14:13:10 2009
@@ -805,7 +805,7 @@
switch(jjstateSet[--i])
{
case 0:
- if ((0x7fffffe87fffffeL & l) != 0L)
+ if ((0x7fffffe87ffffffL & l) != 0L)
{
if (kind > 62)
kind = 62;
@@ -914,7 +914,7 @@
break;
case 62:
case 63:
- if ((0x7fffffe87fffffeL & l) == 0L)
+ if ((0x7fffffe87ffffffL & l) == 0L)
break;
if (kind > 62)
kind = 62;
@@ -925,10 +925,13 @@
jjstateSet[jjnewStateCnt++] = 65;
break;
case 65:
- case 66:
if ((0x7fffffe87fffffeL & l) != 0L)
jjCheckNAddTwoStates(66, 67);
break;
+ case 66:
+ if ((0x7fffffe87ffffffL & l) != 0L)
+ jjCheckNAddTwoStates(66, 67);
+ break;
case 67:
if (curChar == 125 && kind > 63)
kind = 63;
@@ -1563,7 +1566,7 @@
switch(jjstateSet[--i])
{
case 3:
- if ((0x7fffffe87fffffeL & l) != 0L)
+ if ((0x7fffffe87ffffffL & l) != 0L)
{
if (kind > 62)
kind = 62;
@@ -1616,7 +1619,7 @@
break;
case 15:
case 16:
- if ((0x7fffffe87fffffeL & l) == 0L)
+ if ((0x7fffffe87ffffffL & l) == 0L)
break;
if (kind > 62)
kind = 62;
@@ -1627,10 +1630,13 @@
jjstateSet[jjnewStateCnt++] = 18;
break;
case 18:
- case 19:
if ((0x7fffffe87fffffeL & l) != 0L)
jjCheckNAddTwoStates(19, 20);
break;
+ case 19:
+ if ((0x7fffffe87ffffffL & l) != 0L)
+ jjCheckNAddTwoStates(19, 20);
+ break;
case 20:
if (curChar == 125 && kind > 63)
kind = 63;
@@ -2388,7 +2394,7 @@
break;
case 21:
case 22:
- if ((0x7fffffe87fffffeL & l) == 0L)
+ if ((0x7fffffe87ffffffL & l) == 0L)
break;
if (kind > 13)
kind = 13;
@@ -2399,10 +2405,13 @@
jjstateSet[jjnewStateCnt++] = 24;
break;
case 24:
- case 25:
if ((0x7fffffe87fffffeL & l) != 0L)
jjCheckNAddTwoStates(25, 26);
break;
+ case 25:
+ if ((0x7fffffe87ffffffL & l) != 0L)
+ jjCheckNAddTwoStates(25, 26);
+ break;
case 26:
if (curChar == 125 && kind > 13)
kind = 13;
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTDirective.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTDirective.java?rev=735156&r1=735155&r2=735156&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTDirective.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTDirective.java
Fri Jan 16 14:13:10 2009
@@ -30,6 +30,7 @@
import org.apache.velocity.exception.TemplateInitException;
import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.directive.RuntimeMacro;
+import org.apache.velocity.runtime.directive.BlockMacro;
import org.apache.velocity.runtime.parser.ParseException;
import org.apache.velocity.runtime.parser.Parser;
import org.apache.velocity.util.ExceptionUtils;
@@ -124,6 +125,28 @@
directive.setLocation(getLine(), getColumn(),
getTemplateName());
directive.init(rsvc, context,this);
}
+ else if( directiveName.startsWith("@") )
+ {
+ // block macro call (normal macro call but has AST body)
+ directiveName = directiveName.substring(1);
+
+ directive = new BlockMacro(directiveName);
+ directive.setLocation(getLine(), getColumn(),
getTemplateName());
+
+ try
+ {
+ directive.init( rsvc, context, this );
+ }
+ catch (TemplateInitException die)
+ {
+ throw new TemplateInitException(die.getMessage(),
+ (ParseException) die.getWrappedThrowable(),
+ die.getTemplateName(),
+ die.getColumnNumber() + getColumn(),
+ die.getLineNumber() + getLine());
+ }
+ isDirective = true;
+ }
else
{
/**
Modified: velocity/engine/trunk/src/parser/Parser.jjt
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/parser/Parser.jjt?rev=735156&r1=735155&r2=735156&view=diff
==============================================================================
--- velocity/engine/trunk/src/parser/Parser.jjt (original)
+++ velocity/engine/trunk/src/parser/Parser.jjt Fri Jan 16 14:13:10 2009
@@ -1090,8 +1090,8 @@
TOKEN:
{
<#LETTER: [ "a"-"z", "A" - "Z" ] >
-| <#DIRECTIVE_CHAR: [ "a"-"z", "A"-"Z", "0"-"9", "_" ] >
-| <WORD: ( <LETTER> | ["_"]) (<DIRECTIVE_CHAR>)* >
+| <#DIRECTIVE_CHAR: [ "a"-"z", "A"-"Z", "0"-"9", "_", "@" ] >
+| <WORD: ( <LETTER> | ["_"] | ["@"]) (<DIRECTIVE_CHAR>)* >
| <BRACKETED_WORD: "{" ( <LETTER> | ["_"]) (<DIRECTIVE_CHAR>)* "}" >
}
@@ -1456,20 +1456,27 @@
*/
jjtThis.setDirectiveName(directiveName);
-
+
if ( d == null)
{
- /*
- * if null, then not a real directive, but maybe a Velocimacro
- */
-
- isVM = rsvc.isVelocimacro(directiveName, currentTemplateName);
-
- /*
- * Currently, all VMs are LINE directives
- */
-
- directiveType = Directive.LINE;
+ if( directiveName.startsWith("@") )
+ {
+ // block macro call of type: #...@foobar($arg1 $arg2) astBody
#end
+ directiveType = Directive.BLOCK;
+ }
+ else
+ {
+ /*
+ * if null, then not a real directive, but maybe a Velocimacro
+ */
+
+ isVM = rsvc.isVelocimacro(directiveName, currentTemplateName);
+
+ /*
+ * Currently, all VMs are LINE directives
+ */
+ directiveType = Directive.LINE;
+ }
}
else
{