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; } }