gant nested elements completion

This commit is contained in:
peter
2010-06-24 23:25:24 +04:00
parent 4fee3d58f5
commit ac1d681f85
7 changed files with 121 additions and 39 deletions
+1 -1
View File
@@ -19,7 +19,7 @@
<orderEntry type="module" module-name="properties" />
<orderEntry type="module" module-name="execution-openapi" />
<orderEntry type="module" module-name="idea-ui" />
<orderEntry type="module" module-name="dom-openapi" />
<orderEntry type="module" module-name="dom-openapi" exported="" />
<orderEntry type="module" module-name="xml-openapi" />
<orderEntry type="module" module-name="util" />
<orderEntry type="module" module-name="idea-tests" scope="TEST" />
@@ -53,13 +53,13 @@ public class AntDomExtender extends DomExtender<AntDomElement>{
}
else {
final Map<String, Class> 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<String, Class> 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<AntDomElement>{
}
}
else {
final Enumeration nested = parentElementIntrospector.getNestedElements();
final Enumeration<String> 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<AntDomElement>{
}
@Nullable
private static AntIntrospector getIntrospector(Class c) {
public static AntIntrospector getIntrospector(Class c) {
try {
return AntIntrospector.getInstance(c);
}
@@ -99,7 +99,7 @@ public final class AntIntrospector {
return types;
}
public Enumeration getNestedElements() {
public Enumeration<String> getNestedElements() {
return invokeMethod("getNestedElements", false);
}
@@ -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<String> 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;
}
}
@@ -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<LightMethodBuilder> result = new HashSet<LightMethodBuilder>();
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);
}
@@ -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);
}
@@ -106,6 +106,29 @@ def foo() {
checkVariants "ant.patt<caret>t", "patternset"
}
public void testTagsInsideTags() throws Exception {
myFixture.configureByText "a.groovy", """
AntBuilder ant
ant.zip {
patternset {
includ<caret>
}
}"""
myFixture.completeBasic()
assertSameElements myFixture.lookupElementStrings, "include", "includesfile"
}
public void testTagsInsideTagsInGantTarget() throws Exception {
checkVariants """
target(aaa: "") {
zip {
patternset {
includ<caret>
}
}
}""", "include", "includesfile", "includeTargets", "includeTool"
}
static final def GANT_JARS = ["gant.jar", "ant.jar", "ant-junit.jar", "ant-launcher.jar", "commons.jar"]
}