package de.plushnikov.intellij.plugin.agent.transformer;
import de.plushnikov.intellij.plugin.agent.support.SupportedBuild;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
/**
* Transformer that is only required for builds below "146.1154".
*
* @author Alexej Kubarev
*/
@SupportedBuild(max = "146.1154")
public class ModifierVisibilityClassFileTransformer extends AbstractBuildDependentTransformer {
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)
throws IllegalClassFormatException {
if (className.equals("com/intellij/psi/impl/source/PsiModifierListImpl")) {
return doClass(className, classBeingRedefined, classfileBuffer);
} else {
return null;
}
}
private byte[] doClass(String name, Class clazz, byte[] b) {
System.out.println("Modifying class: " + name);
ClassPool pool = ClassPool.getDefault();
CtClass cl = null;
try {
cl = pool.makeClass(new java.io.ByteArrayInputStream(b));
CtMethod m = cl.getDeclaredMethod("hasModifierProperty");
m.insertBefore("{\n"
+ " com.intellij.openapi.extensions.ExtensionPointName pointName = com.intellij.openapi.extensions.ExtensionPointName.create(\"com.intellij.lang.psiAugmentProvider\");\n"
+ " java.lang.Object[] extensions = com.intellij.openapi.extensions.Extensions.getExtensions(pointName);\n"
+ " for (int i = 0; i < extensions.length; i++) {\n"
+ " Object extension = extensions[i];\n"
+ " if(extension.getClass().getName().equals(\"de.plushnikov.intellij.plugin.provider.LombokAugmentProvider\")) {\n"
+ " try {\n"
+ " java.lang.reflect.Method method = extension.getClass().getDeclaredMethod(\"hasModifierProperty\", new java.lang.Class[]{com.intellij.psi.PsiModifierList.class, java.lang.String.class});\n"
+ " java.lang.Boolean augmentation = (java.lang.Boolean)method.invoke(extension, new Object[]{$0, $1});\n"
+ " if (augmentation != null) {\n"
+ " return augmentation.booleanValue();\n"
+ " }\n"
+ " } catch (Exception e) {\n"
+ " System.err.println(e.toString());\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }");
return cl.toBytecode();
} catch (Exception e) {
System.err.println("Could not instrument " + name + ", exception : " + e.getMessage());
return null;
} finally {
if (cl != null) {
cl.detach();
}
}
}
@Override
public boolean canRetransform() {
return true;
}
}