mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
bind pointcut
This commit is contained in:
@@ -90,7 +90,7 @@ public class CustomMembersGenerator implements GdslMembersHolderConsumer {
|
||||
myDepot.addHolder(holder);
|
||||
}
|
||||
|
||||
protected Object[] constructNewArgs(Object[] args) {
|
||||
public Object[] constructNewArgs(Object[] args) {
|
||||
final Object[] newArgs = new Object[args.length + 1];
|
||||
//noinspection ManualArrayCopy
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
|
||||
@@ -1,22 +1,32 @@
|
||||
package org.jetbrains.plugins.groovy.dsl;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.dsl.toplevel.ClassContextFilter;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public abstract class DslPointcut<T> {
|
||||
public abstract class DslPointcut<T,V> {
|
||||
public static Key<Map<String, List>> BOUND = Key.create("gdsl.bound");
|
||||
|
||||
abstract boolean matches(T t, ProcessingContext context);
|
||||
@Nullable
|
||||
abstract List<V> matches(T src, ProcessingContext context);
|
||||
|
||||
abstract boolean operatesOn(Class c);
|
||||
|
||||
public static DslPointcut<GroovyClassDescriptor> currentType(final Object arg) {
|
||||
return new DslPointcut<GroovyClassDescriptor>() {
|
||||
public static DslPointcut<GroovyClassDescriptor, GdslType> currentType(final Object arg) {
|
||||
return new DslPointcut<GroovyClassDescriptor, GdslType>() {
|
||||
|
||||
@Override
|
||||
boolean matches(GroovyClassDescriptor groovyClassDescriptor, ProcessingContext context) {
|
||||
return ClassContextFilter.subtypeOf((String)arg).isApplicable(groovyClassDescriptor, context);
|
||||
List<GdslType> matches(GroovyClassDescriptor src, ProcessingContext context) {
|
||||
if (ClassContextFilter.subtypeOf((String)arg).isApplicable(src, context)) {
|
||||
return Arrays.asList(new GdslType(ClassContextFilter.findPsiType(src, context)));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -26,11 +36,39 @@ public abstract class DslPointcut<T> {
|
||||
};
|
||||
}
|
||||
|
||||
public static <T> DslPointcut<T> unknownPointcut() {
|
||||
return new DslPointcut<T>() {
|
||||
public static DslPointcut bind(final Object arg) {
|
||||
assert arg instanceof Map;
|
||||
assert ((Map)arg).size() == 1;
|
||||
final String name = (String)((Map)arg).keySet().iterator().next();
|
||||
final DslPointcut pct = (DslPointcut)((Map)arg).values().iterator().next();
|
||||
|
||||
return new DslPointcut() {
|
||||
@Override
|
||||
boolean matches(T t, ProcessingContext context) {
|
||||
return true;
|
||||
List matches(Object src, ProcessingContext context) {
|
||||
final List result = pct.matches(src, context);
|
||||
if (result != null) {
|
||||
Map<String, List> map = context.get(BOUND);
|
||||
if (map == null) {
|
||||
context.put(BOUND, map = new HashMap<String, List>());
|
||||
}
|
||||
map.put(name, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean operatesOn(Class c) {
|
||||
return pct.operatesOn(c);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static DslPointcut unknownPointcut() {
|
||||
return new DslPointcut() {
|
||||
|
||||
@Override
|
||||
List matches(Object src, ProcessingContext context) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.jetbrains.plugins.groovy.dsl;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiClassType;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.PsiWildcardType;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class GdslType {
|
||||
private final PsiType myPsiType;
|
||||
|
||||
public GdslType(PsiType psiType) {
|
||||
myPsiType = psiType;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
PsiType type = myPsiType;
|
||||
if (type instanceof PsiWildcardType) {
|
||||
type = ((PsiWildcardType)type).getBound();
|
||||
}
|
||||
if (type instanceof PsiClassType) {
|
||||
final PsiClass resolve = ((PsiClassType)type).resolve();
|
||||
if (resolve != null) {
|
||||
return resolve.getName();
|
||||
}
|
||||
final String canonicalText = type.getCanonicalText();
|
||||
final int i = canonicalText.indexOf('<');
|
||||
if (i < 0) return canonicalText;
|
||||
return canonicalText.substring(0, i);
|
||||
}
|
||||
|
||||
if (type == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return type.getCanonicalText();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.patterns.ElementPattern
|
||||
import com.intellij.patterns.PsiJavaPatterns
|
||||
import com.intellij.util.ProcessingContext
|
||||
import org.jetbrains.plugins.groovy.dsl.dsltop.GdslMembersProvider
|
||||
import org.jetbrains.plugins.groovy.dsl.psi.PsiEnhancerCategory
|
||||
import org.jetbrains.plugins.groovy.dsl.toplevel.CompositeContextFilter
|
||||
import org.jetbrains.plugins.groovy.dsl.toplevel.Context
|
||||
@@ -70,6 +71,7 @@ public class GroovyDslExecutor {
|
||||
mc.contribute = contribute
|
||||
|
||||
mc.currentType = { arg -> DslPointcut.currentType(arg) }
|
||||
mc.bind = { arg -> DslPointcut.bind(arg) }
|
||||
|
||||
oldStylePrimitives(mc)
|
||||
|
||||
@@ -112,11 +114,12 @@ public class GroovyDslExecutor {
|
||||
enhancers << Pair.create(CompositeContextFilter.compose(cts, false), toDo)
|
||||
}
|
||||
|
||||
def processVariants(GroovyClassDescriptor descriptor, consumer, ProcessingContext ctx) {
|
||||
def processVariants(GroovyClassDescriptor descriptor, CustomMembersGenerator consumer, ProcessingContext ctx) {
|
||||
for (pair in enhancers) {
|
||||
if (pair.first.isApplicable(descriptor, ctx)) {
|
||||
Closure f = pair.second.clone()
|
||||
f.delegate = consumer
|
||||
consumer.metaClass = contributionDelegateMetaClass(ctx, consumer)
|
||||
f.resolveStrategy = Closure.DELEGATE_FIRST
|
||||
|
||||
use(cats) {
|
||||
@@ -126,6 +129,29 @@ public class GroovyDslExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
static final def memberProviders = GdslMembersProvider.EP_NAME.getExtensions()
|
||||
|
||||
private ExpandoMetaClass contributionDelegateMetaClass(ProcessingContext ctx, CustomMembersGenerator consumer) {
|
||||
def mc = new ExpandoMetaClass(CustomMembersGenerator)
|
||||
mc.methodMissing = { String name, Object args ->
|
||||
final def newArgs = consumer.constructNewArgs(args)
|
||||
|
||||
// Get other DSL methods from extensions
|
||||
for (d in memberProviders) {
|
||||
final def variants = d.metaClass.respondsTo(d, name, newArgs)
|
||||
if (variants.size() == 1) {
|
||||
return d.invokeMethod(name, newArgs)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
def bound = ctx.get(DslPointcut.BOUND)
|
||||
bound.each { name, value -> mc."$name" = value }
|
||||
mc.initialize()
|
||||
return mc
|
||||
}
|
||||
|
||||
def String toString() {
|
||||
return "${super.toString()}; file = $myFileName";
|
||||
}
|
||||
|
||||
@@ -7,14 +7,14 @@ import org.jetbrains.plugins.groovy.dsl.toplevel.ContextFilter;
|
||||
* @author peter
|
||||
*/
|
||||
public class PointcutContextFilter implements ContextFilter {
|
||||
private final DslPointcut<GroovyClassDescriptor> myPointcut;
|
||||
private final DslPointcut<GroovyClassDescriptor,?> myPointcut;
|
||||
|
||||
public PointcutContextFilter(DslPointcut<GroovyClassDescriptor> pointcut) {
|
||||
public PointcutContextFilter(DslPointcut<GroovyClassDescriptor,?> pointcut) {
|
||||
myPointcut = pointcut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(GroovyClassDescriptor descriptor, ProcessingContext ctx) {
|
||||
return myPointcut.matches(descriptor, ctx);
|
||||
return myPointcut.matches(descriptor, ctx) != null;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,6 +1,5 @@
|
||||
package org.jetbrains.plugins.groovy.dsl.toplevel;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
@@ -11,7 +10,7 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.containers.ConcurrentHashMap;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.dsl.GroovyClassDescriptor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
|
||||
@@ -29,18 +28,19 @@ public class ClassContextFilter implements ContextFilter {
|
||||
|
||||
public boolean isApplicable(GroovyClassDescriptor descriptor, ProcessingContext ctx) {
|
||||
final PsiFile place = descriptor.getPlaceFile();
|
||||
return myPattern.value(Pair.create(findPsiType(descriptor.getProject(), descriptor.getTypeText(), place, ctx), place));
|
||||
return myPattern.value(Pair.create(findPsiType(descriptor, ctx), place));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiType findPsiType(Project project, String typeText, PsiFile place, ProcessingContext ctx) {
|
||||
@NotNull
|
||||
public static PsiType findPsiType(GroovyClassDescriptor descriptor, ProcessingContext ctx) {
|
||||
String typeText = descriptor.getTypeText();
|
||||
final String key = getClassKey(typeText);
|
||||
final Object cached = ctx.get(key);
|
||||
if (cached instanceof PsiType) {
|
||||
return (PsiType)cached;
|
||||
}
|
||||
|
||||
final PsiType found = JavaPsiFacade.getElementFactory(project).createTypeFromText(typeText, place);
|
||||
final PsiType found = JavaPsiFacade.getElementFactory(descriptor.getProject()).createTypeFromText(typeText, descriptor.getPlaceFile());
|
||||
ctx.put(key, found);
|
||||
return found;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@ class DsldTest extends LightGroovyTestCase {
|
||||
'println "".foo + [].<warning>foo</warning>'
|
||||
}
|
||||
|
||||
public void testBind() {
|
||||
checkHighlighting 'contribute(bind(types:currentType("java.lang.CharSequence"))) { property name:types[0].name[-3..-1] }',
|
||||
'println "".ing + "".<warning>foo</warning>'
|
||||
}
|
||||
|
||||
private def checkHighlighting(String dsl, String code) {
|
||||
def file = myFixture.addFileToProject('a.gdsl', dsl)
|
||||
GroovyDslFileIndex.activateUntilModification(file.virtualFile)
|
||||
|
||||
Reference in New Issue
Block a user