mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
reduce class loading - avoid JBTree usage in ReflectionUtil (part 1)
GitOrigin-RevId: 06583bb098c68f92c66e745cae5c815bea0136c7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
648e553590
commit
0d6acb5fb2
@@ -0,0 +1,21 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.util;
|
||||
|
||||
import com.intellij.util.containers.JBIterable;
|
||||
import com.intellij.util.containers.JBTreeTraverser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Do not use in ReflectionUtil and any such low-level and early (start-up) code.
|
||||
*/
|
||||
public final class JBIterableClassTraverser {
|
||||
@NotNull
|
||||
public static JBTreeTraverser<Class<?>> classTraverser(@Nullable Class<?> root) {
|
||||
return CLASS_TRAVERSER.unique().withRoot(root);
|
||||
}
|
||||
|
||||
private static final JBTreeTraverser<Class<?>> CLASS_TRAVERSER = JBTreeTraverser.from(
|
||||
(Function<? super Class<?>, ? extends Iterable<? extends Class<?>>>)aClass -> JBIterable.<Class<?>>of(aClass.getSuperclass())
|
||||
.append(aClass.getInterfaces()));
|
||||
}
|
||||
@@ -4,9 +4,9 @@ package com.intellij.util;
|
||||
import com.intellij.openapi.diagnostic.ControlFlowException;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.DifferenceFilter;
|
||||
import com.intellij.util.containers.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Predicate;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -15,7 +15,7 @@ import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
|
||||
public class ReflectionUtil {
|
||||
public final class ReflectionUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.ReflectionUtil");
|
||||
|
||||
private ReflectionUtil() { }
|
||||
@@ -123,7 +123,7 @@ public class ReflectionUtil {
|
||||
@NotNull
|
||||
public static List<Field> collectFields(@NotNull Class<?> clazz) {
|
||||
List<Field> result = new ArrayList<>();
|
||||
for (Class<?> c : classTraverser(clazz)) {
|
||||
for (Class<?> c : JBIterableClassTraverser.classTraverser(clazz)) {
|
||||
ContainerUtil.addAll(result, c.getDeclaredFields());
|
||||
}
|
||||
return result;
|
||||
@@ -140,16 +140,45 @@ public class ReflectionUtil {
|
||||
@NotNull
|
||||
public static Field findAssignableField(@NotNull Class<?> clazz, @Nullable("null means any type") final Class<?> fieldType, @NotNull final String fieldName) throws NoSuchFieldException {
|
||||
Field result = findFieldInHierarchy(clazz, field -> fieldName.equals(field.getName()) && (fieldType == null || fieldType.isAssignableFrom(field.getType())));
|
||||
if (result != null) return result;
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
throw new NoSuchFieldException("Class: " + clazz + " fieldName: " + fieldName + " fieldType: " + fieldType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Field findFieldInHierarchy(@NotNull Class<?> clazz, @NotNull Condition<? super Field> checker) {
|
||||
for (Class<?> c : classTraverser(clazz)) {
|
||||
Field field = ContainerUtil.find(c.getDeclaredFields(), checker);
|
||||
private static Field findFieldInHierarchy(@NotNull Class<?> rootClass, @NotNull java.util.function.Predicate<? super Field> checker) {
|
||||
for (Class<?> aClass = rootClass; aClass != null; aClass = aClass.getSuperclass()) {
|
||||
for (Field field : aClass.getDeclaredFields()) {
|
||||
if (checker.test(field)) {
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ok, let's check interfaces
|
||||
return processInterfaces(rootClass.getInterfaces(), new HashSet<>(), checker);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Field processInterfaces(@NotNull Class<?>[] interfaces,
|
||||
@NotNull Set<Class<?>> visited,
|
||||
@NotNull java.util.function.Predicate<? super Field> checker) {
|
||||
for (Class<?> anInterface : interfaces) {
|
||||
if (!visited.add(anInterface)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Field field : anInterface.getDeclaredFields()) {
|
||||
if (checker.test(field)) {
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
}
|
||||
}
|
||||
|
||||
Field field = processInterfaces(anInterface.getInterfaces(), visited, checker);
|
||||
if (field != null) {
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
}
|
||||
}
|
||||
@@ -297,7 +326,7 @@ public class ReflectionUtil {
|
||||
|
||||
public static <T> T getField(@NotNull Class<?> objectClass, @Nullable Object object, @Nullable("null means any type") Class<T> fieldType, @NotNull @NonNls String fieldName) {
|
||||
try {
|
||||
final Field field = findAssignableField(objectClass, fieldType, fieldName);
|
||||
Field field = findAssignableField(objectClass, fieldType, fieldName);
|
||||
//noinspection unchecked
|
||||
return (T)field.get(object);
|
||||
}
|
||||
@@ -617,7 +646,7 @@ public class ReflectionUtil {
|
||||
}
|
||||
|
||||
|
||||
private static class MySecurityManager extends SecurityManager {
|
||||
private static final class MySecurityManager extends SecurityManager {
|
||||
private static final MySecurityManager INSTANCE = new MySecurityManager();
|
||||
Class<?>[] getStack() {
|
||||
return getClassContext();
|
||||
@@ -648,12 +677,4 @@ public class ReflectionUtil {
|
||||
public static boolean isAssignable(@NotNull Class<?> ancestor, @NotNull Class<?> descendant) {
|
||||
return ancestor == descendant || ancestor.isAssignableFrom(descendant);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JBTreeTraverser<Class<?>> classTraverser(@Nullable Class<?> root) {
|
||||
return CLASS_TRAVERSER.unique().withRoot(root);
|
||||
}
|
||||
|
||||
private static final JBTreeTraverser<Class<?>> CLASS_TRAVERSER = JBTreeTraverser.from(
|
||||
(Function<? super Class<?>, ? extends Iterable<? extends Class<?>>>)aClass -> JBIterable.<Class<?>>of(aClass.getSuperclass()).append(aClass.getInterfaces()));
|
||||
}
|
||||
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.util.xml;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
@@ -332,15 +318,11 @@ public final class ModelMergerImpl implements ModelMerger {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Method findPrimaryKeyAnnotatedMethod(final Method method, final Class aClass) {
|
||||
if (method.getReturnType() != void.class && method.getParameterTypes().length == 0) {
|
||||
for (Method each : new JavaMethodSignature(method).getAllMethods(aClass)) {
|
||||
if (each.getAnnotation(PrimaryKey.class) != null) {
|
||||
return each;
|
||||
}
|
||||
}
|
||||
private static Method findPrimaryKeyAnnotatedMethod(@NotNull Method sampleMethod, @NotNull Class<?> aClass) {
|
||||
if (sampleMethod.getParameterCount() != 0 || sampleMethod.getReturnType() == void.class) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
return JavaMethodSignature.findMethod(sampleMethod, aClass, method -> method.isAnnotationPresent(PrimaryKey.class));
|
||||
}
|
||||
|
||||
private List<Object> getMergedImplementations(final Method method,
|
||||
|
||||
@@ -1,44 +1,37 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.util.xml;
|
||||
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.JBIterableClassTraverser;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.JBIterable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class JavaMethodSignature {
|
||||
public final class JavaMethodSignature {
|
||||
private static final Set<String> OBJECT_METHOD_NAMES = ContainerUtil.map2Set(Object.class.getDeclaredMethods(), Method::getName);
|
||||
private final String myMethodName;
|
||||
private final Class[] myMethodParameters;
|
||||
private final Class<?>[] myMethodParameters;
|
||||
|
||||
public JavaMethodSignature(final String methodName, final Class... methodParameters) {
|
||||
public JavaMethodSignature(String methodName, Class<?>... methodParameters) {
|
||||
myMethodName = methodName;
|
||||
myMethodParameters = methodParameters.length == 0 ? ArrayUtil.EMPTY_CLASS_ARRAY : methodParameters;
|
||||
}
|
||||
|
||||
public JavaMethodSignature(Method method) {
|
||||
this(method.getName(), method.getParameterTypes());
|
||||
public JavaMethodSignature(@NotNull Method method) {
|
||||
myMethodName = method.getName();
|
||||
myMethodParameters = method.getParameterCount() == 0 ? ArrayUtil.EMPTY_CLASS_ARRAY : method.getParameterTypes();
|
||||
}
|
||||
|
||||
public String getMethodName() {
|
||||
@@ -46,7 +39,7 @@ public class JavaMethodSignature {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public final Method findMethod(final Class aClass) {
|
||||
public final Method findMethod(@NotNull Class<?> aClass) {
|
||||
Method method = getDeclaredMethod(aClass);
|
||||
if (method == null && aClass.isInterface() && OBJECT_METHOD_NAMES.contains(myMethodName)) {
|
||||
method = ReflectionUtil.getDeclaredMethod(Object.class, myMethodName, myMethodParameters);
|
||||
@@ -55,16 +48,19 @@ public class JavaMethodSignature {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Method getDeclaredMethod(final Class aClass) {
|
||||
final Method method = ReflectionUtil.getMethod(aClass, myMethodName, myMethodParameters);
|
||||
private Method getDeclaredMethod(@NotNull Class<?> aClass) {
|
||||
Method method = ReflectionUtil.getMethod(aClass, myMethodName, myMethodParameters);
|
||||
return method == null ? ReflectionUtil.getDeclaredMethod(aClass, myMethodName, myMethodParameters) : method;
|
||||
}
|
||||
|
||||
List<Method> getAllMethods(Class startFrom) {
|
||||
@NotNull
|
||||
List<Method> getAllMethods(@NotNull Class<?> startFrom) {
|
||||
List<Method> result = new ArrayList<>();
|
||||
for (Class superClass : JBIterable.from(ReflectionUtil.classTraverser(startFrom)).append(Object.class).unique()) {
|
||||
for (Class<?> superClass : JBIterable.from(JBIterableClassTraverser.classTraverser(startFrom)).append(Object.class).unique()) {
|
||||
for (Method method : superClass.getDeclaredMethods()) {
|
||||
if (methodMatches(method)) {
|
||||
if (myMethodName.equals(method.getName()) &&
|
||||
method.getParameterCount() == myMethodParameters.length &&
|
||||
Arrays.equals(method.getParameterTypes(), myMethodParameters)) {
|
||||
result.add(method);
|
||||
}
|
||||
}
|
||||
@@ -72,8 +68,24 @@ public class JavaMethodSignature {
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean methodMatches(Method method) {
|
||||
return myMethodName.equals(method.getName()) && Arrays.equals(method.getParameterTypes(), myMethodParameters);
|
||||
@Nullable
|
||||
static Method findMethod(@NotNull Method sampleMethod, @NotNull Class<?> startFrom, @NotNull Predicate<Method> checker) {
|
||||
String sampleMethodName = sampleMethod.getName();
|
||||
Class<?>[] sampleMethodParameters = sampleMethod.getParameterCount() == 0 ? ArrayUtil.EMPTY_CLASS_ARRAY : sampleMethod.getParameterTypes();
|
||||
|
||||
for (Class<?> superClass : JBIterable.from(JBIterableClassTraverser.classTraverser(startFrom)).append(Object.class).unique()) {
|
||||
for (Method method : superClass.getDeclaredMethods()) {
|
||||
if (sampleMethodName.equals(method.getName()) &&
|
||||
method.getParameterCount() == sampleMethodParameters.length &&
|
||||
Arrays.equals(method.getParameterTypes(), sampleMethodParameters)) {
|
||||
if (checker.test(method)) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
||||
Reference in New Issue
Block a user