From d172a725061c44eb129a665bc39149b502405a5a Mon Sep 17 00:00:00 2001 From: Peter Gromov Date: Tue, 7 Apr 2009 18:18:24 +0400 Subject: [PATCH] by-class generated instanceof checker --- .../CaseInsensitiveValuePatternCondition.java | 0 .../src/com/intellij/patterns/CharPattern.java | 0 .../com/intellij/patterns/CollectionPattern.java | 0 .../src/com/intellij/patterns/ElementPattern.java | 0 .../intellij/patterns/ElementPatternCondition.java | 0 .../intellij/patterns/InitialPatternCondition.java | 0 .../src/com/intellij/patterns/ObjectPattern.java | 5 +- .../com/intellij/patterns/PatternCondition.java | 0 .../patterns/PropertyPatternCondition.java | 0 .../com/intellij/patterns/StandardPatterns.java | 0 .../src/com/intellij/patterns/StringPattern.java | 0 .../intellij/patterns/ValuePatternCondition.java | 0 .../intellij/util/InstanceofCheckerGenerator.java | 32 ++++++++ .../util/InstanceofCheckerGeneratorImpl.java | 92 ++++++++++++++++++++++ .../src/META-INF/PlatformExtensions.xml | 2 + 15 files changed, 130 insertions(+), 1 deletion(-) rename {util => platform-api}/src/com/intellij/patterns/CaseInsensitiveValuePatternCondition.java (100%) rename {util => platform-api}/src/com/intellij/patterns/CharPattern.java (100%) rename {util => platform-api}/src/com/intellij/patterns/CollectionPattern.java (100%) rename {util => platform-api}/src/com/intellij/patterns/ElementPattern.java (100%) rename {util => platform-api}/src/com/intellij/patterns/ElementPatternCondition.java (100%) rename {util => platform-api}/src/com/intellij/patterns/InitialPatternCondition.java (100%) rename {util => platform-api}/src/com/intellij/patterns/ObjectPattern.java (94%) rename {util => platform-api}/src/com/intellij/patterns/PatternCondition.java (100%) rename {util => platform-api}/src/com/intellij/patterns/PropertyPatternCondition.java (100%) rename {util => platform-api}/src/com/intellij/patterns/StandardPatterns.java (100%) rename {util => platform-api}/src/com/intellij/patterns/StringPattern.java (100%) rename {util => platform-api}/src/com/intellij/patterns/ValuePatternCondition.java (100%) create mode 100644 platform-api/src/com/intellij/util/InstanceofCheckerGenerator.java create mode 100644 platform-impl/src/com/intellij/util/InstanceofCheckerGeneratorImpl.java diff --git a/util/src/com/intellij/patterns/CaseInsensitiveValuePatternCondition.java b/platform-api/src/com/intellij/patterns/CaseInsensitiveValuePatternCondition.java similarity index 100% rename from util/src/com/intellij/patterns/CaseInsensitiveValuePatternCondition.java rename to platform-api/src/com/intellij/patterns/CaseInsensitiveValuePatternCondition.java diff --git a/util/src/com/intellij/patterns/CharPattern.java b/platform-api/src/com/intellij/patterns/CharPattern.java similarity index 100% rename from util/src/com/intellij/patterns/CharPattern.java rename to platform-api/src/com/intellij/patterns/CharPattern.java diff --git a/util/src/com/intellij/patterns/CollectionPattern.java b/platform-api/src/com/intellij/patterns/CollectionPattern.java similarity index 100% rename from util/src/com/intellij/patterns/CollectionPattern.java rename to platform-api/src/com/intellij/patterns/CollectionPattern.java diff --git a/util/src/com/intellij/patterns/ElementPattern.java b/platform-api/src/com/intellij/patterns/ElementPattern.java similarity index 100% rename from util/src/com/intellij/patterns/ElementPattern.java rename to platform-api/src/com/intellij/patterns/ElementPattern.java diff --git a/util/src/com/intellij/patterns/ElementPatternCondition.java b/platform-api/src/com/intellij/patterns/ElementPatternCondition.java similarity index 100% rename from util/src/com/intellij/patterns/ElementPatternCondition.java rename to platform-api/src/com/intellij/patterns/ElementPatternCondition.java diff --git a/util/src/com/intellij/patterns/InitialPatternCondition.java b/platform-api/src/com/intellij/patterns/InitialPatternCondition.java similarity index 100% rename from util/src/com/intellij/patterns/InitialPatternCondition.java rename to platform-api/src/com/intellij/patterns/InitialPatternCondition.java diff --git a/util/src/com/intellij/patterns/ObjectPattern.java b/platform-api/src/com/intellij/patterns/ObjectPattern.java similarity index 94% rename from util/src/com/intellij/patterns/ObjectPattern.java rename to platform-api/src/com/intellij/patterns/ObjectPattern.java index f14643251e..50e8724d72 100644 --- a/util/src/com/intellij/patterns/ObjectPattern.java +++ b/platform-api/src/com/intellij/patterns/ObjectPattern.java @@ -5,7 +5,9 @@ package com.intellij.patterns; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Condition; import com.intellij.util.ProcessingContext; +import com.intellij.util.InstanceofCheckerGenerator; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,9 +28,10 @@ public abstract class ObjectPattern> impl } protected ObjectPattern(final Class aClass) { + final Condition checker = InstanceofCheckerGenerator.getInstance().getInstanceofChecker(aClass); myCondition = new ElementPatternCondition(new InitialPatternCondition(aClass) { public boolean accepts(@Nullable final Object o, final ProcessingContext context) { - return aClass.isInstance(o); + return checker.value(o); } }); } diff --git a/util/src/com/intellij/patterns/PatternCondition.java b/platform-api/src/com/intellij/patterns/PatternCondition.java similarity index 100% rename from util/src/com/intellij/patterns/PatternCondition.java rename to platform-api/src/com/intellij/patterns/PatternCondition.java diff --git a/util/src/com/intellij/patterns/PropertyPatternCondition.java b/platform-api/src/com/intellij/patterns/PropertyPatternCondition.java similarity index 100% rename from util/src/com/intellij/patterns/PropertyPatternCondition.java rename to platform-api/src/com/intellij/patterns/PropertyPatternCondition.java diff --git a/util/src/com/intellij/patterns/StandardPatterns.java b/platform-api/src/com/intellij/patterns/StandardPatterns.java similarity index 100% rename from util/src/com/intellij/patterns/StandardPatterns.java rename to platform-api/src/com/intellij/patterns/StandardPatterns.java diff --git a/util/src/com/intellij/patterns/StringPattern.java b/platform-api/src/com/intellij/patterns/StringPattern.java similarity index 100% rename from util/src/com/intellij/patterns/StringPattern.java rename to platform-api/src/com/intellij/patterns/StringPattern.java diff --git a/util/src/com/intellij/patterns/ValuePatternCondition.java b/platform-api/src/com/intellij/patterns/ValuePatternCondition.java similarity index 100% rename from util/src/com/intellij/patterns/ValuePatternCondition.java rename to platform-api/src/com/intellij/patterns/ValuePatternCondition.java diff --git a/platform-api/src/com/intellij/util/InstanceofCheckerGenerator.java b/platform-api/src/com/intellij/util/InstanceofCheckerGenerator.java new file mode 100644 index 0000000000..9dd9311e6d --- /dev/null +++ b/platform-api/src/com/intellij/util/InstanceofCheckerGenerator.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved. + * Use is subject to license terms. + */ +package com.intellij.util; + +import com.intellij.openapi.util.Condition; +import org.jetbrains.annotations.Nullable; + +/** + * @author peter + */ +public abstract class InstanceofCheckerGenerator { + private static InstanceofCheckerGenerator ourInstance; + + static { + try { + ourInstance = (InstanceofCheckerGenerator)Class.forName("com.intellij.util.InstanceofCheckerGeneratorImpl").newInstance(); + } + catch (Throwable e) { + throw new RuntimeException(e); + } + } + + public static InstanceofCheckerGenerator getInstance() { + return ourInstance; + } + + @Nullable + public abstract Condition getInstanceofChecker(Class someClass); + +} diff --git a/platform-impl/src/com/intellij/util/InstanceofCheckerGeneratorImpl.java b/platform-impl/src/com/intellij/util/InstanceofCheckerGeneratorImpl.java new file mode 100644 index 0000000000..90ecd58ad9 --- /dev/null +++ b/platform-impl/src/com/intellij/util/InstanceofCheckerGeneratorImpl.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved. + * Use is subject to license terms. + */ +package com.intellij.util; + +import com.intellij.openapi.util.Condition; +import com.intellij.util.containers.ConcurrentFactoryMap; +import net.sf.cglib.asm.ClassVisitor; +import net.sf.cglib.asm.Label; +import net.sf.cglib.asm.Type; +import net.sf.cglib.core.*; + +import java.lang.reflect.Modifier; + +/** + * @author peter + */ +public class InstanceofCheckerGeneratorImpl extends InstanceofCheckerGenerator { + private final ConcurrentFactoryMap> myCache = new ConcurrentFactoryMap>() { + @Override + protected Condition create(Class key) { + return new InstanceofClassGenerator(key).createClass(); + } + }; + + public Condition getInstanceofChecker(final Class someClass) { + return myCache.get(someClass); + } + + private static String toInternalName(Class someClass) { + return someClass.getName().replace('.', '/'); + } + + private static class InstanceofClassGenerator extends AbstractClassGenerator { + private static final Source SOURCE = new Source("IntellijInstanceof"); + private final Class myCheckedClass; + + public InstanceofClassGenerator(Class checkedClass) { + super(SOURCE); + myCheckedClass = checkedClass; + } + + @Override + protected ClassLoader getDefaultClassLoader() { + return myCheckedClass.getClassLoader(); + } + + public Condition createClass() { + return (Condition)super.create(myCheckedClass); + } + + @Override + protected Object firstInstance(Class type) throws Exception { + return type.newInstance(); + } + + @Override + protected Object nextInstance(Object instance) throws Exception { + return instance; + } + + public void generateClass(ClassVisitor classVisitor) throws Exception { + ClassEmitter cv = new ClassEmitter(classVisitor); + + cv.visit(Constants.V1_2, Modifier.PUBLIC, "com/intellij/util/InstanceofChecker$$$$$" + myCheckedClass.getName().replace('.', '$'), toInternalName(Object.class), new String[]{toInternalName(Condition.class)}, Constants.SOURCE_FILE); + final Signature signature = new Signature("", "()V"); + final CodeEmitter cons = cv.begin_method(Modifier.PUBLIC, signature, new Type[0], null); + cons.load_this(); + cons.dup(); + cons.super_invoke_constructor(signature); + cons.return_value(); + cons.end_method(); + + final CodeEmitter e = cv.begin_method(Modifier.PUBLIC, new Signature("value", "(L" + toInternalName(Object.class) + ";)Z"), new Type[0], null); + e.load_arg(0); + e.instance_of(Type.getType(myCheckedClass)); + + Label fail = e.make_label(); + e.if_jump(CodeEmitter.EQ, fail); + e.push(true); + e.return_value(); + + e.mark(fail); + e.push(false); + e.return_value(); + e.end_method(); + + cv.visitEnd(); + } + } +} diff --git a/platform-resources/src/META-INF/PlatformExtensions.xml b/platform-resources/src/META-INF/PlatformExtensions.xml index 55e1e3c23f..afe73d7f22 100644 --- a/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform-resources/src/META-INF/PlatformExtensions.xml @@ -83,6 +83,8 @@ serviceImplementation="com.intellij.featureStatistics.FeatureUsageTrackerImpl"/> + -- 2.11.4.GIT