add versioning support to gdsl
[idea/community.git] / plugins / groovy / src / org / jetbrains / plugins / groovy / dsl / GroovyDslExecutor.groovy
1 package org.jetbrains.plugins.groovy.dsl
2
3 import com.intellij.openapi.application.ApplicationInfo
4 import com.intellij.openapi.util.Pair
5 import com.intellij.openapi.util.text.StringUtil
6 import com.intellij.util.ProcessingContext
7 import org.jetbrains.plugins.groovy.dsl.psi.PsiEnhancerCategory
8 import org.jetbrains.plugins.groovy.dsl.toplevel.CompositeContextFilter
9 import org.jetbrains.plugins.groovy.dsl.toplevel.ContextFilter
10 import org.jetbrains.plugins.groovy.dsl.toplevel.GdslMetaClassProperties
11
12 /**
13  * @author ilyas
14  */
15
16 public class GroovyDslExecutor {
17   static final def cats = PsiEnhancerCategory.EP_NAME.extensions.collect { it.class }
18   final List<Pair<ContextFilter, Closure>> enhancers = []
19   private final String myFileName;
20   static final String ideaVersion
21
22   static {
23     def major = ApplicationInfo.instance.majorVersion
24       def minor = ApplicationInfo.instance.minorVersion
25       def full = major + (minor ? ".$minor" : "")
26     ideaVersion = full
27   }
28
29   public GroovyDslExecutor(String text, String fileName) {
30     myFileName = fileName
31
32     def shell = new GroovyShell()
33     def script = shell.parse(text, fileName)
34
35     def mc = new ExpandoMetaClass(script.class, false)
36     def enhancer = new GdslMetaClassProperties(this)
37
38     // Fill script with necessary properties
39     def properties = enhancer.metaClass.properties
40     for (MetaProperty p in properties) {
41       if (p.getType() == Closure.class) {
42         mc."$p.name" = p.getProperty(enhancer)
43       }
44     }
45
46     mc.supportsVersion = { String ver ->
47       StringUtil.compareVersionNumbers(ideaVersion, ver) >= 0
48     }
49
50     mc.initialize()
51     script.metaClass = mc
52     script.run()
53   }
54
55   def addClassEnhancer(List<ContextFilter> cts, Closure toDo) {
56     enhancers << Pair.create(CompositeContextFilter.compose(cts, false), toDo)
57   }
58
59   def processVariants(GroovyClassDescriptor descriptor, consumer, ProcessingContext ctx) {
60     for (pair in enhancers) {
61       if (pair.first.isApplicable(descriptor, ctx)) {
62         Closure f = pair.second.clone()
63         f.delegate = consumer
64         f.resolveStrategy = Closure.DELEGATE_FIRST
65
66         use(cats) {
67           f.call()
68         }
69       }
70     }
71   }
72
73   def String toString() {
74     return "${super.toString()}; file = $myFileName";
75   }
76
77 }