Skip to content

Commit

Permalink
[fixes projectlombok#3440] Prepend jdt.core classloader to the parser
Browse files Browse the repository at this point in the history
  • Loading branch information
Rawi01 committed Aug 3, 2023
1 parent 9e5e0c3 commit b65b82c
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 42 deletions.
10 changes: 9 additions & 1 deletion src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2021 The Project Lombok Authors.
* Copyright (C) 2009-2023 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -108,6 +108,7 @@ public String mapResourceName(int classFileFormatVersion, String resourceName) {
patchExtensionMethod(sm);
patchRenameField(sm);
patchNullCheck(sm);
patchCrossModuleClassLoading(sm);

patchForTests(sm);

Expand Down Expand Up @@ -1017,6 +1018,13 @@ private static void patchASTNodeSearchUtil(ScriptManager sm) {
.build());
}

private static void patchCrossModuleClassLoading(ScriptManager sm) {
sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
.target(new MethodTarget("org.eclipse.jdt.internal.compiler.parser.Parser", "<clinit>"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$ModuleClassLoading", "parserClinit", "void"))
.build());
}

private static void patchForTests(ScriptManager sm) {
sm.addScriptIfWitness(new String[] {"lombok/eclipse/EclipseTests"}, ScriptBuilder.wrapReturnValue()
.target(new MethodTarget("org.osgi.framework.FrameworkUtil", "getBundle", "org.osgi.framework.Bundle", "java.lang.Class"))
Expand Down
86 changes: 45 additions & 41 deletions src/eclipseAgent/lombok/launch/PatchFixesHider.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010-2021 The Project Lombok Authors.
* Copyright (C) 2010-2023 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -53,6 +53,7 @@
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.core.SourceField;
import org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent;
import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent;
Expand Down Expand Up @@ -156,6 +157,38 @@ private static boolean sameTypes(Class<?>[] types, String[] typeNames) {
}
return true;
}

private static void prependToClassLoader(ClassLoader currentClassLoader, ClassLoader prepend) {
try {
Method prependParentMethod = Permit.getMethod(currentClassLoader.getClass(), "prependParent", ClassLoader.class);
Permit.invoke(prependParentMethod, currentClassLoader, prepend);
} catch (Throwable t) {
// Ignore
}
}

private static ClassLoader findJdtCoreClassLoader(ClassLoader classLoader) {
try {
Method getBundleMethod = Permit.getMethod(classLoader.getClass(), "getBundle");
Object bundle = Permit.invoke(getBundleMethod, classLoader);

Method getBundleContextMethod = Permit.getMethod(bundle.getClass(), "getBundleContext");
Object bundleContext = Permit.invoke(getBundleContextMethod, bundle);

Method getBundlesMethod = Permit.getMethod(bundleContext.getClass(), "getBundles");
Object[] bundles = (Object[]) Permit.invoke(getBundlesMethod, bundleContext);

for (Object searchBundle : bundles) {
if (searchBundle.toString().startsWith("org.eclipse.jdt.core_")) {
Method getModuleClassLoaderMethod = Permit.getMethod(searchBundle.getClass(), "getModuleClassLoader", boolean.class);
return (ClassLoader) Permit.invoke(getModuleClassLoaderMethod, searchBundle, false);
}
}
} catch (Throwable t) {
// Ignore
}
return null;
}
}

/** Contains patch fixes that are dependent on lombok internals. */
Expand Down Expand Up @@ -194,58 +227,29 @@ public static BufferedOutputStream runPostCompiler(BufferedOutputStream out, Str
}
}

public static final class ModuleClassLoading {
public static void parserClinit() {
ClassLoader jdtCoreClassLoader = Util.findJdtCoreClassLoader(Parser.class.getClassLoader());
ClassLoader currentClassLoader = ModuleClassLoading.class.getClassLoader();
Util.prependToClassLoader(currentClassLoader, jdtCoreClassLoader);
}
}

public static final class Transform {
private static Method TRANSFORM;
private static Method TRANSFORM_SWAPPED;

private static synchronized void init(ClassLoader prepend) {
if (TRANSFORM != null) return;

prependClassLoader(prepend);
if (!prepend.toString().contains("org.eclipse.jdt.core:")) {
ClassLoader jdtCoreClassLoader = findJdtCoreClassLoader(prepend);
prependClassLoader(jdtCoreClassLoader);
}
Main.prependClassLoader(prepend);
ClassLoader currentClassLoader = Transform.class.getClassLoader();
Util.prependToClassLoader(currentClassLoader, prepend);
Class<?> shadowed = Util.shadowLoadClass("lombok.eclipse.TransformEclipseAST");
TRANSFORM = Util.findMethodAnyArgs(shadowed, "transform");
TRANSFORM_SWAPPED = Util.findMethodAnyArgs(shadowed, "transform_swapped");
}

private static void prependClassLoader(ClassLoader classLoader) {
Main.prependClassLoader(classLoader);
try {
ClassLoader currentClassLoader = Transform.class.getClassLoader();

Method prependParentMethod = Permit.getMethod(currentClassLoader.getClass(), "prependParent", ClassLoader.class);
Permit.invoke(prependParentMethod, currentClassLoader, classLoader);
} catch (Throwable t) {
// Ignore
}
}

private static ClassLoader findJdtCoreClassLoader(ClassLoader classLoader) {
try {
Method getBundleMethod = Permit.getMethod(classLoader.getClass(), "getBundle");
Object bundle = Permit.invoke(getBundleMethod, classLoader);

Method getBundleContextMethod = Permit.getMethod(bundle.getClass(), "getBundleContext");
Object bundleContext = Permit.invoke(getBundleContextMethod, bundle);

Method getBundlesMethod = Permit.getMethod(bundleContext.getClass(), "getBundles");
Object[] bundles = (Object[]) Permit.invoke(getBundlesMethod, bundleContext);

for (Object searchBundle : bundles) {
if (searchBundle.toString().startsWith("org.eclipse.jdt.core_")) {
Method getModuleClassLoaderMethod = Permit.getMethod(searchBundle.getClass(), "getModuleClassLoader", boolean.class);
return (ClassLoader) Permit.invoke(getModuleClassLoaderMethod, searchBundle, false);
}
}
} catch (Throwable t) {
// Ignore
}
return null;
}

public static void transform(Object parser, Object ast) throws IOException {
init(parser.getClass().getClassLoader());
Util.invokeMethod(TRANSFORM, parser, ast);
Expand Down

0 comments on commit b65b82c

Please sign in to comment.