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> | |||||