From 8670e6cfcf67eaead5c03c4d0517fe40b4eabc2a Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Thu, 8 Aug 2024 09:17:00 +0200 Subject: [PATCH 1/3] use method handles for reflection Signed-off-by: Christian Dietrich --- .../xbase/ui/validation/XbaseUIValidator.java | 53 ++++++++++++++----- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/org.eclipse.xtext.xbase.ui/src/org/eclipse/xtext/xbase/ui/validation/XbaseUIValidator.java b/org.eclipse.xtext.xbase.ui/src/org/eclipse/xtext/xbase/ui/validation/XbaseUIValidator.java index 173b2c7dd2e..56b178371d6 100644 --- a/org.eclipse.xtext.xbase.ui/src/org/eclipse/xtext/xbase/ui/validation/XbaseUIValidator.java +++ b/org.eclipse.xtext.xbase.ui/src/org/eclipse/xtext/xbase/ui/validation/XbaseUIValidator.java @@ -11,8 +11,9 @@ import static com.google.common.collect.Lists.*; import static org.eclipse.xtext.xbase.validation.IssueCodes.*; -import java.lang.reflect.Field; -import java.lang.reflect.Method; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.util.List; import java.util.Map; @@ -239,27 +240,51 @@ protected IClasspathEntry getResolvedClasspathEntry(IJavaProject javaProject, /* } - protected final boolean isJdtCoreVersionAtLeast3390 = JavaCore.getPlugin().getBundle().getVersion().compareTo(new Version(3, 39, 0)) >= 0; + private final static boolean IS_JDT_CORE_VERSION_AT_LEAST3390 = JavaCore.getPlugin().getBundle().getVersion().compareTo(new Version(3, 39, 0)) >= 0; + + private final static MethodHandle GET_ROOT_PATH_TO_RESOLVED_ENTRIES_METHOD_HANDLE = initializeGetRootPathToResolvedEntriesMethodHandle(); + private final static MethodHandle ROOT_PATH_TO_RESOLVED_ENTRIES_FIELD_HANDLE = initializeRootPathToResolvedEntriesFieldHandle(); + protected Map getRootPathToResolvedEntries(PerProjectInfo info) { - if (isJdtCoreVersionAtLeast3390) { + if (IS_JDT_CORE_VERSION_AT_LEAST3390) { + if (GET_ROOT_PATH_TO_RESOLVED_ENTRIES_METHOD_HANDLE == null) { + throw new RuntimeException("getRootPathToResolvedEntries method not found"); + } try { - Method m = PerProjectInfo.class.getDeclaredMethod("getRootPathToResolvedEntries"); - @SuppressWarnings("unchecked") - Map result = (Map) m.invoke(info); + Map result = (Map) GET_ROOT_PATH_TO_RESOLVED_ENTRIES_METHOD_HANDLE.invoke(info); return result; - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); + } catch (Throwable e) { + throw new RuntimeException("failed to call getRootPathToResolvedEntries method", e); } } else { + if (ROOT_PATH_TO_RESOLVED_ENTRIES_FIELD_HANDLE == null) { + throw new RuntimeException("rootPathToResolvedEntries field not found"); + } try { - Field f = PerProjectInfo.class.getDeclaredField("rootPathToResolvedEntries"); - @SuppressWarnings("unchecked") - Map result = (Map) f.get(info); + Map result = (Map) ROOT_PATH_TO_RESOLVED_ENTRIES_FIELD_HANDLE.invoke(info); return result; - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); + } catch (Throwable e) { + throw new RuntimeException("failed to call rootPathToResolvedEntries field", e); } } } + private static MethodHandle initializeRootPathToResolvedEntriesFieldHandle() { + try { + MethodHandle handle = MethodHandles.lookup().findGetter(PerProjectInfo.class, "rootPathToResolvedEntries", Map.class); + return handle; + } catch (ReflectiveOperationException e) { + return null; + } + } + + private static MethodHandle initializeGetRootPathToResolvedEntriesMethodHandle() { + try { + MethodHandle handle = MethodHandles.lookup().findVirtual(PerProjectInfo.class, "getRootPathToResolvedEntries", MethodType.methodType(Map.class)); + return handle; + } catch (ReflectiveOperationException e) { + return null; + } + } + } From a5f7d4266f42ef6c036b5ad911fb883b0f87d7a3 Mon Sep 17 00:00:00 2001 From: Sebastian Zarnekow Date: Thu, 8 Aug 2024 11:07:23 +0200 Subject: [PATCH 2/3] Encapsulate reflective access by single MethodHandle Signed-off-by: Sebastian Zarnekow --- .../xbase/ui/validation/XbaseUIValidator.java | 56 ++++++------------- 1 file changed, 16 insertions(+), 40 deletions(-) diff --git a/org.eclipse.xtext.xbase.ui/src/org/eclipse/xtext/xbase/ui/validation/XbaseUIValidator.java b/org.eclipse.xtext.xbase.ui/src/org/eclipse/xtext/xbase/ui/validation/XbaseUIValidator.java index 56b178371d6..0ef85e06a58 100644 --- a/org.eclipse.xtext.xbase.ui/src/org/eclipse/xtext/xbase/ui/validation/XbaseUIValidator.java +++ b/org.eclipse.xtext.xbase.ui/src/org/eclipse/xtext/xbase/ui/validation/XbaseUIValidator.java @@ -14,10 +14,12 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.util.Collections; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Status; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EStructuralFeature; @@ -239,51 +241,25 @@ protected IClasspathEntry getResolvedClasspathEntry(IJavaProject javaProject, /* return result; } + private final static MethodHandle GET_ROOT_PATH_TO_RESOLVED_ENTRIES = findAccessor(); - private final static boolean IS_JDT_CORE_VERSION_AT_LEAST3390 = JavaCore.getPlugin().getBundle().getVersion().compareTo(new Version(3, 39, 0)) >= 0; - - private final static MethodHandle GET_ROOT_PATH_TO_RESOLVED_ENTRIES_METHOD_HANDLE = initializeGetRootPathToResolvedEntriesMethodHandle(); - private final static MethodHandle ROOT_PATH_TO_RESOLVED_ENTRIES_FIELD_HANDLE = initializeRootPathToResolvedEntriesFieldHandle(); - - protected Map getRootPathToResolvedEntries(PerProjectInfo info) { - if (IS_JDT_CORE_VERSION_AT_LEAST3390) { - if (GET_ROOT_PATH_TO_RESOLVED_ENTRIES_METHOD_HANDLE == null) { - throw new RuntimeException("getRootPathToResolvedEntries method not found"); - } - try { - Map result = (Map) GET_ROOT_PATH_TO_RESOLVED_ENTRIES_METHOD_HANDLE.invoke(info); - return result; - } catch (Throwable e) { - throw new RuntimeException("failed to call getRootPathToResolvedEntries method", e); - } - } else { - if (ROOT_PATH_TO_RESOLVED_ENTRIES_FIELD_HANDLE == null) { - throw new RuntimeException("rootPathToResolvedEntries field not found"); - } - try { - Map result = (Map) ROOT_PATH_TO_RESOLVED_ENTRIES_FIELD_HANDLE.invoke(info); - return result; - } catch (Throwable e) { - throw new RuntimeException("failed to call rootPathToResolvedEntries field", e); - } - } - } - - private static MethodHandle initializeRootPathToResolvedEntriesFieldHandle() { + private static MethodHandle findAccessor() { try { - MethodHandle handle = MethodHandles.lookup().findGetter(PerProjectInfo.class, "rootPathToResolvedEntries", Map.class); - return handle; - } catch (ReflectiveOperationException e) { - return null; + if (JavaCore.getPlugin().getBundle().getVersion().compareTo(new Version(3, 39, 0)) >= 0) { + return MethodHandles.lookup().findGetter(PerProjectInfo.class, "rootPathToResolvedEntries", Map.class); + } else { + return MethodHandles.lookup().findVirtual(PerProjectInfo.class, "getRootPathToResolvedEntries", MethodType.methodType(Map.class)); + } + } catch (Exception e) { + return MethodHandles.dropArguments(MethodHandles.constant(Map.class, Collections.emptyMap()), 0, PerProjectInfo.class); } } - - private static MethodHandle initializeGetRootPathToResolvedEntriesMethodHandle() { + + protected Map getRootPathToResolvedEntries(PerProjectInfo info) throws JavaModelException { try { - MethodHandle handle = MethodHandles.lookup().findVirtual(PerProjectInfo.class, "getRootPathToResolvedEntries", MethodType.methodType(Map.class)); - return handle; - } catch (ReflectiveOperationException e) { - return null; + return (Map) GET_ROOT_PATH_TO_RESOLVED_ENTRIES.invoke(info); + } catch(Throwable t) { + throw new JavaModelException(Status.error(t.getMessage(), t)); } } From 4f325cc5604a56760bdceba0fd9fba18c1b25254 Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Thu, 8 Aug 2024 12:00:17 +0200 Subject: [PATCH 3/3] fix order --- .../eclipse/xtext/xbase/ui/validation/XbaseUIValidator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/org.eclipse.xtext.xbase.ui/src/org/eclipse/xtext/xbase/ui/validation/XbaseUIValidator.java b/org.eclipse.xtext.xbase.ui/src/org/eclipse/xtext/xbase/ui/validation/XbaseUIValidator.java index 0ef85e06a58..4acaec41917 100644 --- a/org.eclipse.xtext.xbase.ui/src/org/eclipse/xtext/xbase/ui/validation/XbaseUIValidator.java +++ b/org.eclipse.xtext.xbase.ui/src/org/eclipse/xtext/xbase/ui/validation/XbaseUIValidator.java @@ -246,10 +246,10 @@ protected IClasspathEntry getResolvedClasspathEntry(IJavaProject javaProject, /* private static MethodHandle findAccessor() { try { if (JavaCore.getPlugin().getBundle().getVersion().compareTo(new Version(3, 39, 0)) >= 0) { - return MethodHandles.lookup().findGetter(PerProjectInfo.class, "rootPathToResolvedEntries", Map.class); - } else { return MethodHandles.lookup().findVirtual(PerProjectInfo.class, "getRootPathToResolvedEntries", MethodType.methodType(Map.class)); - } + } else { + return MethodHandles.lookup().findGetter(PerProjectInfo.class, "rootPathToResolvedEntries", Map.class); + } } catch (Exception e) { return MethodHandles.dropArguments(MethodHandles.constant(Map.class, Collections.emptyMap()), 0, PerProjectInfo.class); }