diff --git a/plugins/ant/ant.iml b/plugins/ant/ant.iml
index d0adaec1ca6e..23e5720400f3 100644
--- a/plugins/ant/ant.iml
+++ b/plugins/ant/ant.iml
@@ -19,7 +19,7 @@
-
+
diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomExtender.java b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomExtender.java
index b3692cb2642e..b64dd2b01b2c 100644
--- a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomExtender.java
+++ b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomExtender.java
@@ -53,13 +53,13 @@ public class AntDomExtender extends DomExtender{
}
else {
final Map tasks = reflected.getTaskDefinitions();
- final Class taskClass = (Class)tasks.get(tagName);
+ final Class taskClass = tasks.get(tagName);
if (taskClass != null) {
parentElementIntrospector = getIntrospector(taskClass);
}
else {
final Map dataTypes = reflected.getDataTypeDefinitions();
- final Class dataClass = (Class)dataTypes.get(tagName);
+ final Class dataClass = dataTypes.get(tagName);
if (dataClass != null) {
parentElementIntrospector = getIntrospector(dataClass);
}
@@ -83,9 +83,9 @@ public class AntDomExtender extends DomExtender{
}
}
else {
- final Enumeration nested = parentElementIntrospector.getNestedElements();
+ final Enumeration nested = parentElementIntrospector.getNestedElements();
while (nested.hasMoreElements()) {
- registerChild(registrar, genericInfo, (String)nested.nextElement());
+ registerChild(registrar, genericInfo, nested.nextElement());
}
}
}
@@ -113,7 +113,7 @@ public class AntDomExtender extends DomExtender{
}
@Nullable
- private static AntIntrospector getIntrospector(Class c) {
+ public static AntIntrospector getIntrospector(Class c) {
try {
return AntIntrospector.getInstance(c);
}
diff --git a/plugins/ant/src/com/intellij/lang/ant/psi/impl/AntIntrospector.java b/plugins/ant/src/com/intellij/lang/ant/psi/impl/AntIntrospector.java
index 596e9cdb6eaf..42acaa1d4454 100644
--- a/plugins/ant/src/com/intellij/lang/ant/psi/impl/AntIntrospector.java
+++ b/plugins/ant/src/com/intellij/lang/ant/psi/impl/AntIntrospector.java
@@ -99,7 +99,7 @@ public final class AntIntrospector {
return types;
}
- public Enumeration getNestedElements() {
+ public Enumeration getNestedElements() {
return invokeMethod("getNestedElements", false);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntBuilderMethod.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntBuilderMethod.java
new file mode 100644
index 000000000000..f569794d0736
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntBuilderMethod.java
@@ -0,0 +1,59 @@
+package org.jetbrains.plugins.groovy.gant;
+
+import com.intellij.lang.ant.dom.AntDomExtender;
+import com.intellij.lang.ant.psi.impl.AntIntrospector;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.light.LightMethodBuilder;
+import com.intellij.psi.scope.PsiScopeProcessor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.GroovyFileType;
+import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter;
+import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
+
+import java.util.Enumeration;
+
+/**
+* @author peter
+*/
+class AntBuilderMethod extends LightMethodBuilder {
+ private final PsiFile myPlace;
+ @Nullable private final Class myAntClass;
+
+ public AntBuilderMethod(PsiFile place, String name, PsiType closureType, @Nullable Class antClass) {
+ super(place.getManager(), GroovyFileType.GROOVY_LANGUAGE, name);
+ myPlace = place;
+ myAntClass = antClass;
+ setModifiers(PsiModifier.PUBLIC);
+ addParameter("args", CommonClassNames.JAVA_UTIL_MAP);
+ setBaseIcon(GantIcons.ANT_TASK);
+ addParameter(new GrLightParameter("body", closureType, this).setOptional(true));
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getNavigationElement() {
+ if (myAntClass != null) {
+ final PsiClass psiClass = JavaPsiFacade.getInstance(getProject()).findClass(myAntClass.getName(), myPlace.getResolveScope());
+ if (psiClass != null) {
+ return psiClass;
+ }
+ }
+ return this;
+ }
+
+ public boolean processNestedElements(PsiScopeProcessor processor) {
+ final AntIntrospector introspector = AntDomExtender.getIntrospector(myAntClass);
+ if (introspector != null) {
+ final Enumeration nested = introspector.getNestedElements();
+ while (nested.hasMoreElements()) {
+ final AntBuilderMethod method =
+ new AntBuilderMethod(myPlace, nested.nextElement(), getParameterList().getParameters()[1].getType(), null);
+ if (!ResolveUtil.processElement(processor, method)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntTasksProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntTasksProvider.java
index b987f4f51a87..8114d61f725b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntTasksProvider.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntTasksProvider.java
@@ -27,18 +27,15 @@ import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightMethodBuilder;
-import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.util.PathUtil;
import com.intellij.util.lang.UrlClassLoader;
-import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.extensions.GroovyScriptType;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
-import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter;
import java.net.URL;
import java.util.*;
@@ -79,29 +76,12 @@ public class AntTasksProvider {
final Set result = new HashSet();
final Project project = file.getProject();
- final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
- final GlobalSearchScope scope = file.getResolveScope();
-
- final PsiType closureType = JavaPsiFacade.getElementFactory(project).createTypeFromText(GrClosableBlock.GROOVY_LANG_CLOSURE,
- file);
+ final PsiType closureType = JavaPsiFacade.getElementFactory(project).createTypeFromText(GrClosableBlock.GROOVY_LANG_CLOSURE, file);
for (String name : antObjects.keySet()) {
- final PsiClass psiClass = facade.findClass(antObjects.get(name).getName(), scope);
-
- final LightMethodBuilder tdMethod =
- new LightMethodBuilder(PsiManager.getInstance(project), GroovyFileType.GROOVY_LANGUAGE, name).
- setModifiers(PsiModifier.PUBLIC).
- addParameter("args", CommonClassNames.JAVA_UTIL_MAP).
- setBaseIcon(GantIcons.ANT_TASK);
-
- tdMethod.addParameter(new GrLightParameter("body", closureType, tdMethod).setOptional(true));
-
- if (psiClass != null) {
- tdMethod.setNavigationElement(psiClass);
- }
- result.add(tdMethod);
+ result.add(new AntBuilderMethod(file, name, closureType, antObjects.get(name)));
}
- return Result.create(result, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT, ProjectRootManager.getInstance(file.getProject()));
+ return Result.create(result, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT, ProjectRootManager.getInstance(project));
}
}, false);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/GantMemberContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/GantMemberContributor.java
index ed8162023a2b..205a067e9945 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/GantMemberContributor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/GantMemberContributor.java
@@ -15,10 +15,7 @@
*/
package org.jetbrains.plugins.groovy.gant;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiNamedElement;
-import com.intellij.psi.PsiType;
+import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightMethodBuilder;
import com.intellij.psi.impl.light.LightVariableBuilder;
import com.intellij.psi.scope.PsiScopeProcessor;
@@ -26,6 +23,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersProcessor;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
@@ -45,13 +43,35 @@ public class GantMemberContributor implements NonCodeMembersProcessor {
return true;
}
- PsiFile file = place.getContainingFile();
- if (!GantUtils.isGantScriptFile(file)) {
+ GrClosableBlock closure = PsiTreeUtil.getContextOfType(place, GrClosableBlock.class, true);
+ if (closure == null) {
return true;
}
- final GrClosableBlock closure = PsiTreeUtil.getContextOfType(place, GrClosableBlock.class, true);
- if (closure == null) {
+ boolean antTasksProcessed = false;
+ while (closure != null) {
+ final PsiElement parent = closure.getParent();
+ if (parent instanceof GrMethodCall) {
+ final PsiMethod method = ((GrMethodCall)parent).resolveMethod();
+ if (method instanceof AntBuilderMethod) {
+ antTasksProcessed = true;
+ if (!processAntTasks(processor, place)) {
+ return false;
+ }
+ if (!((AntBuilderMethod)method).processNestedElements(processor)) {
+ return false;
+ }
+ break;
+ }
+ }
+
+ closure = PsiTreeUtil.getContextOfType(closure, GrClosableBlock.class, true);
+ }
+
+ // ------- gant-specific
+
+ PsiFile file = place.getContainingFile();
+ if (!GantUtils.isGantScriptFile(file)) {
return true;
}
@@ -66,7 +86,7 @@ public class GantMemberContributor implements NonCodeMembersProcessor {
}
}
- return processAntTasks(processor, place);
+ return antTasksProcessed || processAntTasks(processor, place);
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/gant/completion/GantReferenceCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/gant/completion/GantReferenceCompletionTest.groovy
index e2bd83205322..4dad2bc7c506 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/gant/completion/GantReferenceCompletionTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/gant/completion/GantReferenceCompletionTest.groovy
@@ -106,6 +106,29 @@ def foo() {
checkVariants "ant.pattt", "patternset"
}
+ public void testTagsInsideTags() throws Exception {
+ myFixture.configureByText "a.groovy", """
+AntBuilder ant
+ant.zip {
+ patternset {
+ includ
+ }
+}"""
+ myFixture.completeBasic()
+ assertSameElements myFixture.lookupElementStrings, "include", "includesfile"
+ }
+
+ public void testTagsInsideTagsInGantTarget() throws Exception {
+ checkVariants """
+target(aaa: "") {
+ zip {
+ patternset {
+ includ
+ }
+ }
+}""", "include", "includesfile", "includeTargets", "includeTool"
+ }
+
static final def GANT_JARS = ["gant.jar", "ant.jar", "ant-junit.jar", "ant-launcher.jar", "commons.jar"]
}