diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DomGenericInfoEx.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DomGenericInfoEx.java index 8ccaca91a5a2..6f1e1b487a19 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/DomGenericInfoEx.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DomGenericInfoEx.java @@ -34,6 +34,7 @@ public abstract class DomGenericInfoEx implements DomGenericInfo { public abstract boolean checkInitialized(); + @Nullable public abstract Invocation createInvocation(final JavaMethod method); @NotNull diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java index 61b1bab28c3c..10ea2943c418 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java @@ -21,8 +21,6 @@ import com.intellij.semantic.SemElement; import com.intellij.semantic.SemKey; import com.intellij.semantic.SemService; import com.intellij.util.*; -import com.intellij.util.containers.ConcurrentFactoryMap; -import com.intellij.util.containers.FactoryMap; import com.intellij.util.xml.*; import com.intellij.util.xml.events.DomEvent; import com.intellij.util.xml.reflect.*; @@ -49,8 +47,8 @@ public abstract class DomInvocationHandler myScalarConverters = new FactoryMap() { - protected Converter create(final JavaMethod method) { - final Type returnType = method.getGenericReturnType(); - final Type type = returnType == void.class ? method.getGenericParameterTypes()[0] : returnType; - final Class parameter = ReflectionUtil.substituteGenericType(type, myType); - LOG.assertTrue(parameter != null, type + " " + myType); - Converter converter = getConverter(new AnnotatedElement() { - @Override - public T getAnnotation(Class annotationClass) { - return myInvocationCache.getMethodAnnotation(method, annotationClass); - } - }, parameter); - if (converter == null && type instanceof TypeVariable) { - converter = getConverter(DomInvocationHandler.this, DomUtil.getGenericValueParameter(myType)); - } - if (converter == null) { - converter = myManager.getConverterManager().getConverterByClass(parameter); - } - if (converter == null) { - throw new AssertionError("No converter specified: String<->" + parameter.getName() + "; method=" + method + "; place=" + myChildDescription); - } - return converter; - } - }; - private final FactoryMap myAccessorInvocations = new ConcurrentFactoryMap() { - @Override - protected Invocation create(Method signature) { - final JavaMethod method = JavaMethod.getMethod(getRawType(), signature); - - if (myInvocationCache.isTagValueGetter(method)) { - return new GetInvocation(getScalarConverter(method)); - } - - if (myInvocationCache.isTagValueSetter(method)) { - return new SetInvocation(getScalarConverter(method)); - } - return null; - } - }; + private volatile Converter myScalarConverter = null; + private volatile SmartFMap myAccessorInvocations = SmartFMap.emptyMap(); protected DomInvocationHandler(Type type, DomParentStrategy parentStrategy, final EvaluatedXmlName tagName, @@ -110,7 +71,6 @@ public abstract class DomInvocationHandler T getAnnotation(Class annotationClass) { + return myInvocationCache.getMethodAnnotation(method, annotationClass); + } + }, parameter); + if (converter == null && type instanceof TypeVariable) { + converter = getConverter(DomInvocationHandler.this, DomUtil.getGenericValueParameter(myType)); + } + if (converter == null) { + converter = myManager.getConverterManager().getConverterByClass(parameter); + } + if (converter == null) { + throw new AssertionError("No converter specified: String<->" + parameter.getName() + "; method=" + method + "; place=" + myChildDescription); } - assert converter != null; return converter; } @@ -546,7 +526,7 @@ public abstract class DomInvocationHandler T _getParentOfType(Class requiredClass, DomElement element) { - while (element != null && !(requiredClass.isInstance(element))) { + while (element != null && !requiredClass.isInstance(element)) { element = element.getParent(); } return (T)element; @@ -609,24 +589,39 @@ public abstract class DomInvocationHandler handler, final Object[] args) throws Throwable { try { - return handler.getScalarConverter(getValue); + return handler.getScalarConverter(); } catch (Throwable e) { final Throwable cause = e.getCause(); diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/StaticGenericInfo.java b/xml/dom-impl/src/com/intellij/util/xml/impl/StaticGenericInfo.java index f0259671a803..8d07d3e1952f 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/StaticGenericInfo.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/StaticGenericInfo.java @@ -150,7 +150,7 @@ public class StaticGenericInfo extends DomGenericInfoEx { return new AddChildInvocation(getTypeGetter(method), getIndexGetter(method), description, description.getType()); } - throw new RuntimeException("No implementation for method " + method.toString() + " in class " + myClass); + return null; } private static Function getTypeGetter(final JavaMethod method) { diff --git a/xml/dom-openapi/src/com/intellij/util/xml/JavaMethod.java b/xml/dom-openapi/src/com/intellij/util/xml/JavaMethod.java index 0802a0450be4..193380f5e3a1 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/JavaMethod.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/JavaMethod.java @@ -15,9 +15,9 @@ */ package com.intellij.util.xml; -import com.intellij.util.containers.ConcurrentFactoryMap; -import com.intellij.util.containers.FactoryMap; +import com.intellij.util.SmartFMap; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; import java.lang.annotation.Annotation; import java.lang.reflect.Method; @@ -33,17 +33,7 @@ public final class JavaMethod implements AnnotatedElement{ private final JavaMethodSignature mySignature; private final Class myDeclaringClass; private final Method myMethod; - private final FactoryMap myAnnotationsMap = new ConcurrentFactoryMap() { - protected Annotation create(Class annotationClass) { - for (Method method : mySignature.getAllMethods(myDeclaringClass)) { - final Annotation annotation = method.getAnnotation(annotationClass); - if (annotation != null) { - return annotation; - } - } - return null; - } - }; + private volatile SmartFMap myAnnotationsMap = SmartFMap.emptyMap(); private JavaMethod(final Class declaringClass, final JavaMethodSignature signature) { mySignature = signature; @@ -102,7 +92,22 @@ public final class JavaMethod implements AnnotatedElement{ } public final T getAnnotation(Class annotationClass) { - return (T)myAnnotationsMap.get(annotationClass); + //noinspection unchecked + T annotation = (T)myAnnotationsMap.get(annotationClass); + if (annotation == null) { + myAnnotationsMap = myAnnotationsMap.plus(annotationClass, annotation = findAnnotation(annotationClass)); + } + return annotation; + } + + @Nullable private T findAnnotation(Class annotationClass) { + for (Method method : mySignature.getAllMethods(myDeclaringClass)) { + final T annotation = method.getAnnotation(annotationClass); + if (annotation != null) { + return annotation; + } + } + return null; } @Override