From 8dd4e0ba76f304d2a1bfde2ddd614d750d83560f Mon Sep 17 00:00:00 2001
From: Peter Reilly
Date: Wed, 3 Dec 2003 13:16:01 +0000
Subject: [PATCH] Change ${x} to @{x} for attribute notation of macrodef
git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275731 13f79535-47bb-0310-9956-ffa450edef68
---
build.xml | 4 +-
docs/manual/CoreTasks/macrodef.html | 35 ++++++-----
docs/manual/CoreTypes/antlib.html | 4 +-
src/etc/testcases/taskdefs/macrodef.xml | 18 ++++--
.../apache/tools/ant/taskdefs/MacroDef.java | 52 ++++++++++++++---
.../tools/ant/taskdefs/MacroInstance.java | 58 +++++++++++++------
.../tools/ant/taskdefs/MacroDefTest.java | 5 ++
7 files changed, 129 insertions(+), 47 deletions(-)
diff --git a/build.xml b/build.xml
index ec7790e74..b9ccf8479 100644
--- a/build.xml
+++ b/build.xml
@@ -817,10 +817,10 @@
-
-
+
diff --git a/docs/manual/CoreTasks/macrodef.html b/docs/manual/CoreTasks/macrodef.html
index 2e462d805..efce64230 100644
--- a/docs/manual/CoreTasks/macrodef.html
+++ b/docs/manual/CoreTasks/macrodef.html
@@ -3,6 +3,11 @@
MacroDef Task
+
@@ -49,8 +54,12 @@
This attribute is placed in the body of the templated
- task using the ant property notation - ${attribute name}.
- Note that is not an actual ant property.
+ task using a notation similar to the ant property notation
+ - @{attribute name}. (May be remembered as "put the substitution
+ AT this location").
+ The escape sequence @@{x} is used to allow @{x} to be
+ placed in the text without substitution of x.
+ This corresponds to the $${x} escape sequence for properties
@@ -107,12 +116,12 @@
runs it.
-
+
<macrodef name="testing">
<attribute name="v" default="NOT SET"/>
<element name="some-tasks" optional="yes"/>
<sequential>
- <echo>v is ${v}</echo>
+ <echo>v is @{v}</echo>
<some-tasks/>
</sequential>
</macrodef>
@@ -122,7 +131,7 @@
<echo>this is a test</echo>
</some-tasks>
</testing>
-
+
The following fragment defines a task called <call-cc> which
@@ -132,29 +141,29 @@
ant-contrib project.
-
+
<macrodef name="call-cc">
<attribute name="target"/>
<attribute name="link"/>
<attribute name="target.dir"/>
<element name="cc-elements"/>
<sequential>
- <mkdir dir="${obj.dir}/${target}"/>
- <mkdir dir="${target.dir}"/>
- <cc link="${link}" objdir="${obj.dir}/${target}"
- outfile="${target.dir}/${target}">
+ <mkdir dir="${obj.dir}/@{target}"/>
+ <mkdir dir="@{target.dir}"/>
+ <cc link="@{link}" objdir="${obj.dir}/@{target}"
+ outfile="@{target.dir}/@{target}">
<compiler refid="compiler.options"/>
<cc-elements/>
</cc>
</sequential>
</macrodef>
-
+
This then can be used as follows:
-
+
<call-cc target="unittests" link="executable"
target.dir="${build.bin.dir}">
<cc-elements>
@@ -165,7 +174,7 @@
<linker refid="linker-libs"/>
</cc-elements>
</call-cc>
-
+
Copyright © 2003 Apache Software
diff --git a/docs/manual/CoreTypes/antlib.html b/docs/manual/CoreTypes/antlib.html
index 6bdbd87f5..79459b4a7 100644
--- a/docs/manual/CoreTypes/antlib.html
+++ b/docs/manual/CoreTypes/antlib.html
@@ -89,7 +89,7 @@
<attribute name="dir"/>
<sequential>
<antcontrib:shellscript shell="bash"> <!-- HERE -->
- ls -Rl ${dir}
+ ls -Rl @{dir}
</antcontrib:shellscript>
</sequential>
</macrodef>
@@ -132,7 +132,7 @@
<element name="do"/>
<sequential>
<current:if>
- <current:isallowed test="${action}"/>
+ <current:isallowed test="@{action}"/>
<current:then>
<current:do/>
</current:then>
diff --git a/src/etc/testcases/taskdefs/macrodef.xml b/src/etc/testcases/taskdefs/macrodef.xml
index 705a65ff9..67e4024f3 100644
--- a/src/etc/testcases/taskdefs/macrodef.xml
+++ b/src/etc/testcases/taskdefs/macrodef.xml
@@ -4,7 +4,7 @@
-
+
@@ -14,7 +14,7 @@
- ${text}
+ @{text}
@@ -25,7 +25,7 @@
- ${text}
+ @{text}
@@ -44,7 +44,7 @@
-
+
@@ -65,4 +65,14 @@
+
+
+
+
+ @@{prop} is '@{prop}', value of $${@{prop}} is '${@{prop}}'
+
+
+
+
+
diff --git a/src/main/org/apache/tools/ant/taskdefs/MacroDef.java b/src/main/org/apache/tools/ant/taskdefs/MacroDef.java
index 8aa801938..0cada1721 100644
--- a/src/main/org/apache/tools/ant/taskdefs/MacroDef.java
+++ b/src/main/org/apache/tools/ant/taskdefs/MacroDef.java
@@ -78,8 +78,8 @@ import org.apache.tools.ant.UnknownElement;
public class MacroDef extends AntlibDefinition {
private NestedSequential nestedSequential;
private String name;
- private Map attributes = new HashMap();
- private Map elements = new HashMap();
+ private List attributes = new ArrayList();
+ private Map elements = new HashMap();
/**
* Name of the definition
@@ -170,7 +170,7 @@ public class MacroDef extends AntlibDefinition {
/**
* @return the nested Attributes
*/
- public Map getAttributes() {
+ public List getAttributes() {
return attributes;
}
@@ -221,12 +221,15 @@ public class MacroDef extends AntlibDefinition {
throw new BuildException(
"the attribute nested element needed a \"name\" attribute");
}
- if (attributes.get(attribute.getName()) != null) {
- throw new BuildException(
- "the attribute " + attribute.getName()
- + " has already been specified");
+ for (int i = 0; i < attributes.size(); ++i) {
+ if (((Attribute) attributes.get(i)).getName().equals(
+ attribute.getName())) {
+ throw new BuildException(
+ "the attribute " + attribute.getName()
+ + " has already been specified");
+ }
}
- attributes.put(attribute.getName(), attribute);
+ attributes.add(attribute);
}
/**
@@ -347,6 +350,13 @@ public class MacroDef extends AntlibDefinition {
}
return true;
}
+
+ /**
+ * @return a hash code value for this object.
+ */
+ public int hashCode() {
+ return objectHashCode(defaultValue) + objectHashCode(name);
+ }
}
/**
@@ -416,6 +426,13 @@ public class MacroDef extends AntlibDefinition {
}
return optional == other.optional;
}
+
+ /**
+ * @return a hash code value for this object.
+ */
+ public int hashCode() {
+ return objectHashCode(name) + (optional ? 1 : 0);
+ }
}
/**
@@ -463,6 +480,17 @@ public class MacroDef extends AntlibDefinition {
return true;
}
+ /**
+ * @return a hash code value for this object.
+ */
+ public int hashCode() {
+ return objectHashCode(name)
+ + objectHashCode(getURI())
+ + objectHashCode(nestedSequential)
+ + objectHashCode(attributes)
+ + objectHashCode(elements);
+ }
+
/**
* extends AntTypeDefinition, on create
* of the object, the template macro definition
@@ -526,4 +554,12 @@ public class MacroDef extends AntlibDefinition {
return macroDef.equals(otherDef.macroDef);
}
}
+
+ private static int objectHashCode(Object o) {
+ if (o == null) {
+ return 0;
+ } else {
+ return o.hashCode();
+ }
+ }
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java b/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java
index 93e046e1c..a71cb458e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java
+++ b/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java
@@ -87,7 +87,6 @@ public class MacroInstance extends Task implements DynamicConfigurator {
private Map nsElements = null;
private Map presentElements = new HashMap();
private Hashtable localProperties = new Hashtable();
-
/**
* Called from MacroDef.MyAntTypeDefinition#create()
@@ -142,7 +141,7 @@ public class MacroInstance extends Task implements DynamicConfigurator {
}
return nsElements;
}
-
+
/**
* Embedded element in macro instance
*/
@@ -166,11 +165,15 @@ public class MacroInstance extends Task implements DynamicConfigurator {
}
}
- private static final int STATE_NORMAL = 0;
+ private static final int STATE_NORMAL = 0;
private static final int STATE_EXPECT_BRACKET = 1;
- private static final int STATE_EXPECT_NAME = 2;
-
+ private static final int STATE_EXPECT_NAME = 2;
+ private static final int STATE_EXPECT_EXCAPE = 3;
+
private String macroSubs(String s, Map macroMapping) {
+ if (s == null) {
+ return null;
+ }
StringBuffer ret = new StringBuffer();
StringBuffer macroName = null;
boolean inMacro = false;
@@ -179,48 +182,67 @@ public class MacroInstance extends Task implements DynamicConfigurator {
char ch = s.charAt(i);
switch (state) {
case STATE_NORMAL:
- if (ch == '$') {
- state = 1;
+ if (ch == '@') {
+ state = STATE_EXPECT_BRACKET;
} else {
ret.append(ch);
- }
+ }
break;
case STATE_EXPECT_BRACKET:
if (ch == '{') {
- state = 2;
+ state = STATE_EXPECT_NAME;
macroName = new StringBuffer();
+ } else if (ch == '@') {
+ state = STATE_EXPECT_EXCAPE;
} else {
- state = 0;
- ret.append('$');
+ state = STATE_NORMAL;
+ ret.append('@');
ret.append(ch);
}
break;
case STATE_EXPECT_NAME:
if (ch == '}') {
- state = 0;
+ state = STATE_NORMAL;
String name = macroName.toString();
String value = (String) macroMapping.get(name);
if (value == null) {
- ret.append("${" + name + "}");
+ ret.append("@{" + name + "}");
} else {
ret.append(value);
}
macroName = null;
} else {
- macroName.append(s.charAt(i));
+ macroName.append(ch);
+ }
+ break;
+ case STATE_EXPECT_EXCAPE:
+ state = STATE_NORMAL;
+ if (ch == '{') {
+ ret.append("@");
+ } else {
+ ret.append("@@");
}
+ ret.append(ch);
+ break;
+ default:
+ break;
}
}
switch (state) {
case STATE_NORMAL:
break;
case STATE_EXPECT_BRACKET:
- ret.append('$');
+ ret.append('@');
break;
case STATE_EXPECT_NAME:
- ret.append("${");
+ ret.append("@{");
ret.append(macroName.toString());
break;
+ case STATE_EXPECT_EXCAPE:
+ ret.append("@@");
+ break;
+ default:
+ break;
}
return ret.toString();
@@ -294,12 +316,12 @@ public class MacroInstance extends Task implements DynamicConfigurator {
public void execute() {
localProperties = new Hashtable();
Set copyKeys = new HashSet(map.keySet());
- for (Iterator i = macroDef.getAttributes().values().iterator();
- i.hasNext();) {
+ for (Iterator i = macroDef.getAttributes().iterator(); i.hasNext();) {
MacroDef.Attribute attribute = (MacroDef.Attribute) i.next();
String value = (String) map.get(attribute.getName());
if (value == null) {
value = attribute.getDefault();
+ value = macroSubs(value, localProperties);
}
if (value == null) {
throw new BuildException(
diff --git a/src/testcases/org/apache/tools/ant/taskdefs/MacroDefTest.java b/src/testcases/org/apache/tools/ant/taskdefs/MacroDefTest.java
index eb57c482e..1556134e4 100644
--- a/src/testcases/org/apache/tools/ant/taskdefs/MacroDefTest.java
+++ b/src/testcases/org/apache/tools/ant/taskdefs/MacroDefTest.java
@@ -98,5 +98,10 @@ public class MacroDefTest extends BuildFileTest {
expectLog("nested", "A nested element");
}
+ public void testDouble() {
+ expectLog(
+ "double",
+ "@{prop} is 'property', value of ${property} is 'A property value'");
+ }
}