Improve the resolution of the extension point to bind to: - first try the extension point which might be in the same file - then try the one in the root file Still some work to do: there might be intermediate file in the import stack which we would to resolve the name against, but the ProjectHelper doesn't hold the prefix stacking. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@1373326 13f79535-47bb-0310-9956-ffa450edef68master
@@ -88,6 +88,9 @@ Other changes: | |||||
and extension points. | and extension points. | ||||
Bugzilla Report 53549. | Bugzilla Report 53549. | ||||
* Make extension point bindable to imported prefixed targets | |||||
Bugzilla Report 53550. | |||||
Changes from Ant 1.8.3 TO Ant 1.8.4 | Changes from Ant 1.8.3 TO Ant 1.8.4 | ||||
=================================== | =================================== | ||||
@@ -629,27 +629,52 @@ public class ProjectHelper { | |||||
public void resolveExtensionOfAttributes(Project project) | public void resolveExtensionOfAttributes(Project project) | ||||
throws BuildException { | throws BuildException { | ||||
for (String[] extensionInfo : getExtensionStack()) { | for (String[] extensionInfo : getExtensionStack()) { | ||||
String tgName = extensionInfo[0]; | |||||
String name = extensionInfo[1]; | |||||
String extPointName = extensionInfo[0]; | |||||
String targetName = extensionInfo[1]; | |||||
OnMissingExtensionPoint missingBehaviour = OnMissingExtensionPoint.valueOf(extensionInfo[2]); | OnMissingExtensionPoint missingBehaviour = OnMissingExtensionPoint.valueOf(extensionInfo[2]); | ||||
// if the file has been included or imported, it may have a prefix | |||||
// we should consider when trying to resolve the target it is | |||||
// extending | |||||
String prefixAndSep = extensionInfo.length > 3 ? extensionInfo[3] : null; | |||||
// find the target we're extending | |||||
Hashtable projectTargets = project.getTargets(); | Hashtable projectTargets = project.getTargets(); | ||||
if (!projectTargets.containsKey(tgName)) { | |||||
String message = "can't add target " + name | |||||
+ " to extension-point " + tgName | |||||
Target extPoint = null; | |||||
if (prefixAndSep == null) { | |||||
// no prefix - not from an imported/included build file | |||||
extPoint = (Target) projectTargets.get(extPointName); | |||||
} else { | |||||
// we have a prefix, which means we came from an include/import | |||||
// FIXME: here we handle no particular level of include. We try | |||||
// the fully prefixed name, and then the non-prefixed name. But | |||||
// there might be intermediate project in the import stack, | |||||
// which prefix should be tested before testing the non-prefix | |||||
// root name. | |||||
extPoint = (Target) projectTargets.get(prefixAndSep + extPointName); | |||||
if (extPoint == null) { | |||||
extPoint = (Target) projectTargets.get(extPointName); | |||||
} | |||||
} | |||||
// make sure we found a point to extend on | |||||
if (extPoint == null) { | |||||
String message = "can't add target " + targetName | |||||
+ " to extension-point " + extPointName | |||||
+ " because the extension-point is unknown."; | + " because the extension-point is unknown."; | ||||
if (missingBehaviour == OnMissingExtensionPoint.FAIL) { | if (missingBehaviour == OnMissingExtensionPoint.FAIL) { | ||||
throw new BuildException(message); | throw new BuildException(message); | ||||
} else if (missingBehaviour == OnMissingExtensionPoint.WARN) { | } else if (missingBehaviour == OnMissingExtensionPoint.WARN) { | ||||
Target target = (Target) projectTargets.get(name); | |||||
project.log(target, "Warning: " + message, Project.MSG_WARN); | |||||
Target t = (Target) projectTargets.get(targetName); | |||||
project.log(t, "Warning: " + message, Project.MSG_WARN); | |||||
} | } | ||||
} else { | } else { | ||||
Target t = (Target) projectTargets.get(tgName); | |||||
if (!(t instanceof ExtensionPoint)) { | |||||
throw new BuildException("referenced target " + tgName | |||||
if (!(extPoint instanceof ExtensionPoint)) { | |||||
throw new BuildException("referenced target " + extPointName | |||||
+ " is not an extension-point"); | + " is not an extension-point"); | ||||
} | } | ||||
t.addDependency(name); | |||||
extPoint.addDependency(targetName); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -1011,17 +1011,24 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
ProjectHelper helper = | ProjectHelper helper = | ||||
(ProjectHelper) context.getProject(). | (ProjectHelper) context.getProject(). | ||||
getReference(ProjectHelper.PROJECTHELPER_REFERENCE); | getReference(ProjectHelper.PROJECTHELPER_REFERENCE); | ||||
for (String tgName : Target.parseDepends(extensionPoint, name, "extensionOf")) { | |||||
if (isInIncludeMode()) { | |||||
tgName = prefix + sep + tgName; | |||||
} | |||||
for (String extPointName : Target.parseDepends(extensionPoint, name, "extensionOf")) { | |||||
if (extensionPointMissing == null) { | if (extensionPointMissing == null) { | ||||
extensionPointMissing = OnMissingExtensionPoint.FAIL; | extensionPointMissing = OnMissingExtensionPoint.FAIL; | ||||
} | } | ||||
// defer extensionpoint resolution until the full | // defer extensionpoint resolution until the full | ||||
// import stack has been processed | // import stack has been processed | ||||
helper.getExtensionStack().add(new String[] { | |||||
tgName, name, extensionPointMissing.name() }); | |||||
if (isInIncludeMode()) { | |||||
// if in include mode, provide prefix we're including by | |||||
// so that we can try and resolve extension point from | |||||
// the local file first | |||||
helper.getExtensionStack().add( | |||||
new String[] {extPointName, target.getName(), | |||||
extensionPointMissing.name(), prefix + sep}); | |||||
} else { | |||||
helper.getExtensionStack().add( | |||||
new String[] {extPointName, target.getName(), | |||||
extensionPointMissing.name()}); | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -0,0 +1,34 @@ | |||||
<?xml version="1.0"?> | |||||
<!-- | |||||
Licensed to the Apache Software Foundation (ASF) under one or more | |||||
contributor license agreements. See the NOTICE file distributed with | |||||
this work for additional information regarding copyright ownership. | |||||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||||
(the "License"); you may not use this file except in compliance with | |||||
the License. You may obtain a copy of the License at | |||||
http://www.apache.org/licenses/LICENSE-2.0 | |||||
Unless required by applicable law or agreed to in writing, software | |||||
distributed under the License is distributed on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
See the License for the specific language governing permissions and | |||||
limitations under the License. | |||||
--> | |||||
<project xmlns:au="antlib:org.apache.ant.antunit" default="antunit"> | |||||
<import file="../../antunit-base.xml" /> | |||||
<!-- declare a target that depends on the extension point --> | |||||
<target name="compile" depends="all.compile" /> | |||||
<!-- declare our extension point --> | |||||
<extension-point name="all.compile" /> | |||||
<!-- import all our modules --> | |||||
<import file="module1.xml" as="module1" /> | |||||
<target name="testImport" depends="compile"> | |||||
<au:assertLogContains text="In module1 compile. Yay!" /> | |||||
</target> | |||||
</project> |
@@ -0,0 +1,25 @@ | |||||
<?xml version="1.0"?> | |||||
<!-- | |||||
Licensed to the Apache Software Foundation (ASF) under one or more | |||||
contributor license agreements. See the NOTICE file distributed with | |||||
this work for additional information regarding copyright ownership. | |||||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||||
(the "License"); you may not use this file except in compliance with | |||||
the License. You may obtain a copy of the License at | |||||
http://www.apache.org/licenses/LICENSE-2.0 | |||||
Unless required by applicable law or agreed to in writing, software | |||||
distributed under the License is distributed on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
See the License for the specific language governing permissions and | |||||
limitations under the License. | |||||
--> | |||||
<project name="module1"> | |||||
<!-- declare a target with the same name as one in the master --> | |||||
<target name="compile" extensionOf="all.compile"> | |||||
<echo message="In module1 compile. Yay!"/> | |||||
</target> | |||||
</project> |