diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslExecutor.groovy b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslExecutor.groovy index 43107b78f5e8..3e71b9cb4096 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslExecutor.groovy +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslExecutor.groovy @@ -8,6 +8,7 @@ import org.jetbrains.plugins.groovy.dsl.psi.PsiEnhancerCategory import org.jetbrains.plugins.groovy.dsl.toplevel.CompositeContextFilter import org.jetbrains.plugins.groovy.dsl.toplevel.ContextFilter import org.jetbrains.plugins.groovy.dsl.toplevel.GdslMetaClassProperties +import com.intellij.openapi.project.Project /** * @author ilyas @@ -16,13 +17,15 @@ import org.jetbrains.plugins.groovy.dsl.toplevel.GdslMetaClassProperties public class GroovyDslExecutor { static final def cats = PsiEnhancerCategory.EP_NAME.extensions.collect { it.class } final List> enhancers = [] + final List> categoryEnhancers = [] + private final String myFileName; static final String ideaVersion static { def major = ApplicationInfo.instance.majorVersion - def minor = ApplicationInfo.instance.minorVersion - def full = major + (minor ? ".$minor" : "") + def minor = ApplicationInfo.instance.minorVersion + def full = major + (minor ? ".$minor" : "") ideaVersion = full } @@ -56,6 +59,10 @@ public class GroovyDslExecutor { enhancers << Pair.create(CompositeContextFilter.compose(cts, false), toDo) } + def addCategoryEnhancer(Closure toDo) { + categoryEnhancers << toDo + } + def processVariants(GroovyClassDescriptor descriptor, consumer, ProcessingContext ctx) { for (pair in enhancers) { if (pair.first.isApplicable(descriptor, ctx)) { @@ -70,6 +77,18 @@ public class GroovyDslExecutor { } } + def processCategoryVariants(Project project, consumer) { + for (enhancer in categoryEnhancers) { + Closure f = enhancer.clone() + f.delegate = consumer + f.resolveStrategy = Closure.DELEGATE_FIRST + + use(cats) { + f.call() + } + } + } + def String toString() { return "${super.toString()}; file = $myFileName"; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/GdslMetaClassProperties.groovy b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/GdslMetaClassProperties.groovy index a9d401bfe57c..3e030c560429 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/GdslMetaClassProperties.groovy +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/GdslMetaClassProperties.groovy @@ -42,6 +42,10 @@ class GdslMetaClassProperties { } } + Closure staticContributor = { Closure toDo -> + myExecutor.addCategoryEnhancer toDo + } + /** * Auxiliary methods for context definition */ diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GDKSuperMethodSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GDKSuperMethodSearcher.java index 830f769f1ea6..d04a8bf4a468 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GDKSuperMethodSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GDKSuperMethodSearcher.java @@ -57,7 +57,7 @@ public class GDKSuperMethodSearcher implements QueryExecutor> myDefaultMethods; private GrTypeDefinition myArrayClass; private final ConcurrentWeakHashMap myCalculatedTypes = new ConcurrentWeakHashMap(); + private volatile boolean myRebuildGdkPending = true; private final GroovyShortNamesCache myCache; private final TypeInferenceHelper myTypeInferenceHelper; @@ -78,6 +84,7 @@ public class GroovyPsiManager { public void rootsChanged(ModuleRootEvent event) { dropTypesCache(); + myRebuildGdkPending = true; } }); } @@ -90,6 +97,40 @@ public class GroovyPsiManager { myCalculatedTypes.clear(); } + + public List getDefaultMethods(String qName) { + if (myRebuildGdkPending) { + final Map> gdk = buildGDK(); + if (myRebuildGdkPending) { + myDefaultMethods = gdk; + myRebuildGdkPending = false; + } + } + + List methods = myDefaultMethods.get(qName); + if (methods == null) return Collections.emptyList(); + return methods; + } + + private Map> buildGDK() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public List getDefaultMethods(PsiClass psiClass) { + List list = new ArrayList(); + getDefaultMethodsInner(psiClass, new HashSet(), list); + return list; + } + + public void getDefaultMethodsInner(PsiClass psiClass, Set watched, List methods) { + if (watched.contains(psiClass)) return; + watched.add(psiClass); + methods.addAll(getDefaultMethods(psiClass.getQualifiedName())); + for (PsiClass aClass : psiClass.getSupers()) { + getDefaultMethodsInner(aClass, watched, methods); + } + } + public void addCategoryMethods(String fromClass, Map> toMap, NotNullFunction converter) { PsiClass categoryClass = JavaPsiFacade.getInstance(myProject).findClass(fromClass, GlobalSearchScope.allScope(myProject)); if (categoryClass != null) {