Merge branch 'netbeans'

This commit is contained in:
Reinier Zwitserloot committed 2009-12-02 00:06:25 +01:00
commit d2fc0df773
20 files changed
+518 -47

No files matched your search

+9 -5
View File
@@ -2,17 +2,21 @@
<classpath>
<classpathentry kind="src" path="src/core"/>
<classpathentry kind="src" path="src/eclipseAgent"/>
<classpathentry kind="src" path="src/netbeansAgent"/>
<classpathentry kind="src" path="src/installer"/>
<classpathentry kind="src" path="src/delombok"/>
<classpathentry kind="src" path="experimental/src"/>
<classpathentry kind="src" path="test/delombok/src"/>
<classpathentry kind="src" path="test/core/src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="deps/lombok/org.eclipse.jdt.core_3.5.0.v_963.jar"/>
<classpathentry kind="lib" path="deps/lombok/org.eclipse.jdt.ui_3.5.1.r351_v20090821-0800.jar"/>
<classpathentry kind="lib" path="deps/lombok/org.eclipse.core.runtime_3.5.0.v20090525.jar"/>
<classpathentry kind="lib" path="deps/lombok/org.eclipse.osgi_3.5.0.v20090520.jar"/>
<classpathentry kind="lib" path="deps/lombok/org.eclipse.equinox.common_3.5.0.v20090520-1800.jar"/>
<classpathentry kind="lib" path="deps/lombok/eclipse/org.eclipse.jdt.core_3.5.0.v_963.jar"/>
<classpathentry kind="lib" path="deps/lombok/eclipse/org.eclipse.jdt.ui_3.5.1.r351_v20090821-0800.jar"/>
<classpathentry kind="lib" path="deps/lombok/eclipse/org.eclipse.core.runtime_3.5.0.v20090525.jar"/>
<classpathentry kind="lib" path="deps/lombok/eclipse/org.eclipse.osgi_3.5.0.v20090520.jar"/>
<classpathentry kind="lib" path="deps/lombok/eclipse/org.eclipse.equinox.common_3.5.0.v20090520-1800.jar"/>
<classpathentry kind="lib" path="deps/lombok/netbeans/boot_6.8beta.jar"/>
<classpathentry kind="lib" path="deps/lombok/netbeans/org-openide-util_6.8beta.jar"/>
<classpathentry kind="lib" path="deps/lombok/netbeans/org-netbeans-modules-java-source_6.8beta.jar"/>
<classpathentry kind="lib" path="deps/junit-4.7.jar"/>
<classpathentry kind="lib" path="deps/lombok/ant.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/lombok.patcher"/>
+7 -1
View File
@@ -83,6 +83,7 @@ lombok code including the various agents.
<sourcePath path="src/core" />
<sourcePath path="src/installer" />
<sourcePath path="src/eclipseAgent" />
<sourcePath path="src/netbeansAgent" />
<sourcePath path="src/delombok" />
<class location="build/lombok/lombok" />
</findbugs>
@@ -119,8 +120,10 @@ lombok code including the various agents.
<javac debug="on" destdir="build/lombok" target="1.6" source="1.6">
<src path="src/core" />
<src path="src/delombok" />
<src path="src/netbeansAgent" />
<include name="lombok/javac/**" />
<include name="lombok/delombok/**" />
<include name="lombok/netbeans/**" />
<classpath location="build/lombok" />
<classpath refid="deps.path" />
<classpath refid="libs.path" />
@@ -135,6 +138,9 @@ lombok code including the various agents.
<fileset dir="src/eclipseAgent">
<patternset refid="copyables" />
</fileset>
<fileset dir="src/netbeansAgent">
<patternset refid="copyables" />
</fileset>
<fileset dir="src/delombok">
<patternset refid="copyables" />
</fileset>
@@ -153,7 +159,7 @@ lombok code including the various agents.
<fileset dir="build" includes="changelog.txt" />
<fileset dir="." includes="LICENCE" />
<manifest>
<attribute name="Premain-Class" value="lombok.eclipse.agent.EclipsePatcher" />
<attribute name="Premain-Class" value="lombok.core.Agent" />
<attribute name="Can-Redefine-Classes" value="true" />
<attribute name="Main-Class" value="lombok.core.Main" />
<attribute name="Lombok-Version" value="${lombok.version}" />
-1
View File
@@ -1 +0,0 @@
Empty dir placeholder
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
Empty dir placeholder
+62
View File
@@ -0,0 +1,62 @@
/*
* Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package lombok.core;
import java.lang.instrument.Instrumentation;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public abstract class Agent {
protected abstract void runAgent(String agentArgs, Instrumentation instrumentation, boolean injected) throws Exception;
public static void agentmain(String agentArgs, Instrumentation instrumentation) throws Exception {
runAgents(agentArgs, instrumentation, true);
}
public static void premain(String agentArgs, Instrumentation instrumentation) throws Exception {
runAgents(agentArgs, instrumentation, false);
}
private static final List<String> AGENT_NAMES = Collections.unmodifiableList(Arrays.asList(
"lombok.netbeans.agent.NetbeansPatcher",
"lombok.eclipse.agent.EclipsePatcher"
));
private static void runAgents(String agentArgs, Instrumentation instrumentation, boolean injected) throws Exception {
for (String agentName : AGENT_NAMES) {
try {
Class<?> agentClass = Class.forName(agentName);
Agent agent = (Agent) agentClass.newInstance();
agent.runAgent(agentArgs, instrumentation, injected);
} catch (ClassNotFoundException e) {
//That's okay - this lombok evidently is a version with support for something stripped out.
} catch (ClassCastException e) {
throw new InternalError("Lombok bug. Class: " + agentName + " is not an implementation of lombok.core.Agent");
} catch (IllegalAccessException e) {
throw new InternalError("Lombok bug. Class: " + agentName + " is not public");
} catch (InstantiationException e) {
throw new InternalError("Lombok bug. Class: " + agentName + " is not concrete or has no public no-args constructor");
}
}
}
}
+19 -30
View File
@@ -21,14 +21,12 @@
*/
package lombok.javac;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import javax.annotation.processing.Messager;
import javax.tools.Diagnostic;
@@ -85,46 +83,36 @@ public class HandlerLibrary {
public static HandlerLibrary load(Messager messager) {
HandlerLibrary library = new HandlerLibrary(messager);
loadAnnotationHandlers(library);
loadVisitorHandlers(library);
try {
loadAnnotationHandlers(library);
loadVisitorHandlers(library);
} catch (IOException e) {
System.err.println("Lombok isn't running due to misconfigured SPI files: " + e);
}
return library;
}
/** Uses SPI Discovery to find implementations of {@link JavacAnnotationHandler}. */
@SuppressWarnings("unchecked")
private static void loadAnnotationHandlers(HandlerLibrary lib) {
private static void loadAnnotationHandlers(HandlerLibrary lib) throws IOException {
//No, that seemingly superfluous reference to JavacAnnotationHandler's classloader is not in fact superfluous!
Iterator<JavacAnnotationHandler> it = ServiceLoader.load(JavacAnnotationHandler.class,
JavacAnnotationHandler.class.getClassLoader()).iterator();
while (it.hasNext()) {
try {
JavacAnnotationHandler<?> handler = it.next();
Class<? extends Annotation> annotationClass =
SpiLoadUtil.findAnnotationClass(handler.getClass(), JavacAnnotationHandler.class);
AnnotationHandlerContainer<?> container = new AnnotationHandlerContainer(handler, annotationClass);
if (lib.annotationHandlers.put(container.annotationClass.getName(), container) != null) {
lib.javacWarning("Duplicate handlers for annotation type: " + container.annotationClass.getName());
}
lib.typeLibrary.addType(container.annotationClass.getName());
} catch (ServiceConfigurationError e) {
lib.javacWarning("Can't load Lombok annotation handler for javac", e);
for (JavacAnnotationHandler handler : SpiLoadUtil.findServices(JavacAnnotationHandler.class, JavacAnnotationHandler.class.getClassLoader())) {
Class<? extends Annotation> annotationClass =
SpiLoadUtil.findAnnotationClass(handler.getClass(), JavacAnnotationHandler.class);
AnnotationHandlerContainer<?> container = new AnnotationHandlerContainer(handler, annotationClass);
if (lib.annotationHandlers.put(container.annotationClass.getName(), container) != null) {
lib.javacWarning("Duplicate handlers for annotation type: " + container.annotationClass.getName());
}
lib.typeLibrary.addType(container.annotationClass.getName());
}
}
/** Uses SPI Discovery to find implementations of {@link JavacASTVisitor}. */
private static void loadVisitorHandlers(HandlerLibrary lib) {
private static void loadVisitorHandlers(HandlerLibrary lib) throws IOException {
//No, that seemingly superfluous reference to JavacASTVisitor's classloader is not in fact superfluous!
Iterator<JavacASTVisitor> it = ServiceLoader.load(JavacASTVisitor.class,
JavacASTVisitor.class.getClassLoader()).iterator();
while (it.hasNext()) {
try {
JavacASTVisitor handler = it.next();
lib.visitorHandlers.add(handler);
} catch (ServiceConfigurationError e) {
lib.javacWarning("Can't load Lombok visitor handler for javac", e);
}
for (JavacASTVisitor visitor : SpiLoadUtil.findServices(JavacASTVisitor.class, JavacASTVisitor.class.getClassLoader())) {
lib.visitorHandlers.add(visitor);
}
}
@@ -177,6 +165,7 @@ public class HandlerLibrary {
if (container == null) continue;
try {
System.out.println("Calling handle on: "+ container.handler.getClass().getName());
handled |= container.handle(node);
} catch (AnnotationValueDecodeFail fail) {
fail.owner.setError(fail.getMessage(), fail.idx);
+1
View File
@@ -125,6 +125,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
/** @return A TreeMaker instance that you can use to create new AST nodes. */
public TreeMaker getTreeMaker() {
treeMaker.at(-1);
return treeMaker;
}
@@ -26,6 +26,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import lombok.core.Agent;
import lombok.patcher.Hook;
import lombok.patcher.MethodTarget;
import lombok.patcher.ScriptManager;
@@ -41,15 +42,10 @@ import lombok.patcher.scripts.ScriptBuilder;
* classes in this package for more information about which classes are transformed and how they are
* transformed.
*/
public class EclipsePatcher {
private EclipsePatcher() {}
public static void agentmain(@SuppressWarnings("unused") String agentArgs, Instrumentation instrumentation) throws Exception {
registerPatchScripts(instrumentation, true);
}
public static void premain(@SuppressWarnings("unused") String agentArgs, Instrumentation instrumentation) throws Exception {
registerPatchScripts(instrumentation, false);
public class EclipsePatcher extends Agent {
@Override
public void runAgent(String agentArgs, Instrumentation instrumentation, boolean injected) throws Exception {
registerPatchScripts(instrumentation, injected);
}
private static void registerPatchScripts(Instrumentation instrumentation, boolean reloadExistingClasses) {
@@ -0,0 +1,75 @@
/*
* Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package lombok.netbeans.agent;
import java.util.Collections;
import javax.annotation.processing.Messager;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.tools.Diagnostic.Kind;
import lombok.javac.JavacTransformer;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.util.Context;
public class NetbeansEntryPoint implements TaskListener {
public class DummyMessager implements Messager {
@Override public void printMessage(Kind kind, CharSequence msg) {
System.err.printf("%s: %s\n", kind, msg);
}
@Override public void printMessage(Kind kind, CharSequence msg, Element e) {
printMessage(kind, msg);
}
@Override public void printMessage(Kind kind, CharSequence msg, Element e, AnnotationMirror a) {
printMessage(kind, msg);
}
@Override public void printMessage(Kind kind, CharSequence msg, Element e, AnnotationMirror a, AnnotationValue v) {
printMessage(kind, msg);
}
}
private final Context context;
public NetbeansEntryPoint(Context context) {
this.context = context;
}
@Override public void started(TaskEvent event) {
//we run at the end, so all the action is in #finished.
}
@Override public void finished(TaskEvent event) {
if (TaskEvent.Kind.PARSE == event.getKind()) {
JavacTransformer transformer = new JavacTransformer(new DummyMessager()); //TODO hook into netbeans error reporting!
JCCompilationUnit compilationUnit = (JCCompilationUnit) event.getCompilationUnit();
transformer.transform(context, Collections.singleton(compilationUnit));
}
}
}
@@ -0,0 +1,135 @@
/*
* Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package lombok.netbeans.agent;
import java.lang.instrument.Instrumentation;
import lombok.core.Agent;
import lombok.patcher.Hook;
import lombok.patcher.MethodTarget;
import lombok.patcher.ScriptManager;
import lombok.patcher.StackRequest;
import lombok.patcher.scripts.ScriptBuilder;
/**
* This is a java-agent that patches some of netbeans's classes so that lombok is initialized as Javac TaskListener,
* allowing us to change AST nodes anytime netbeans parses source code. It also fixes some of the places in netbeans that
* can't deal with generated code.
*
* The hard work on figuring out where to patch has been done by Jan Lahoda (jlahoda@netbeans.org)
*/
public class NetbeansPatcher extends Agent {
@Override
public void runAgent(String agentArgs, Instrumentation instrumentation, boolean injected) throws Exception {
registerPatchScripts(instrumentation, injected);
}
private static void registerPatchScripts(Instrumentation instrumentation, boolean reloadExistingClasses) {
ScriptManager sm = new ScriptManager();
sm.registerTransformer(instrumentation);
patchNetbeansClassLoader(sm);
patchNetbeansJavac(sm);
patchNetbeansMissingPositionAwareness(sm);
if (reloadExistingClasses) sm.reloadClasses(instrumentation);
}
private static void patchNetbeansClassLoader(ScriptManager sm) {
sm.addScript(ScriptBuilder.exitEarly()
.transplant().request(StackRequest.PARAM1, StackRequest.PARAM2)
.target(new MethodTarget("org.netbeans.StandardModule$OneModuleClassLoader", "<init>"))
.decisionMethod(new Hook("lombok/netbeans/agent/PatchFixes", "addSelfToClassLoader", "(Lorg/netbeans/Module;Ljava/util/List;)Z"))
.build());
sm.addScript(ScriptBuilder.exitEarly()
.transplant()
.request(StackRequest.THIS, StackRequest.PARAM1)
.target(new MethodTarget("org.netbeans.ProxyClassLoader", "getResource"))
.decisionMethod(new Hook("lombok/netbeans/agent/PatchFixes", "getResource_decision", "(Ljava/lang/ClassLoader;Ljava/lang/String;)Z"))
.valueMethod(new Hook("lombok/netbeans/agent/PatchFixes", "getResource_value", "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/net/URL;"))
.build());
sm.addScript(ScriptBuilder.exitEarly()
.transplant()
.request(StackRequest.THIS, StackRequest.PARAM1)
.target(new MethodTarget("org.netbeans.ProxyClassLoader", "getResources"))
.decisionMethod(new Hook("lombok/netbeans/agent/PatchFixes", "getResources_decision", "(Ljava/lang/ClassLoader;Ljava/lang/String;)Z"))
.valueMethod(new Hook("lombok/netbeans/agent/PatchFixes", "getResources_value", "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/util/Enumeration;"))
.build());
sm.addScript(ScriptBuilder.exitEarly()
.transplant()
.target(new MethodTarget("org.netbeans.ProxyClassLoader", "loadClass"))
.request(StackRequest.THIS, StackRequest.PARAM1)
.decisionMethod(new Hook("lombok/netbeans/agent/PatchFixes", "loadClass_decision", "(Ljava/lang/ClassLoader;Ljava/lang/String;)Z"))
.valueMethod(new Hook("lombok/netbeans/agent/PatchFixes", "loadClass_value", "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;"))
.build());
}
private static void patchNetbeansJavac(ScriptManager sm) {
sm.addScript(ScriptBuilder.wrapReturnValue()
.request(StackRequest.THIS, StackRequest.PARAM1)
.transplant()
.target(new MethodTarget("com.sun.tools.javac.api.JavacTaskImpl", "setTaskListener"))
.wrapMethod(new Hook("lombok/netbeans/agent/PatchFixes", "fixContentOnSetTaskListener",
"(Lcom/sun/tools/javac/api/JavacTaskImpl;Lcom/sun/source/util/TaskListener;)V"))
.build());
sm.addScript(ScriptBuilder.wrapReturnValue()
.request(StackRequest.RETURN_VALUE, StackRequest.PARAM1)
.transplant()
.target(new MethodTarget("org.netbeans.modules.java.source.parsing.JavacParser", "createJavacTask",
"com.sun.tools.javac.api.JavacTaskImpl",
"org.netbeans.api.java.source.ClasspathInfo", "javax.tools.DiagnosticListener", "java.lang.String", "boolean",
"com.sun.tools.javac.api.ClassNamesForFileOraculum", "com.sun.tools.javac.util.CancelService"))
.wrapMethod(new Hook("lombok/netbeans/agent/PatchFixes", "addTaskListenerWhenCallingJavac",
"(Lcom/sun/tools/javac/api/JavacTaskImpl;Lorg/netbeans/api/java/source/ClasspathInfo;)V"))
.build());
}
private static void patchNetbeansMissingPositionAwareness(ScriptManager sm) {
sm.addScript(ScriptBuilder.replaceMethodCall()
.target(new MethodTarget("org.netbeans.modules.java.editor.overridden.ComputeAnnotations",
"createAnnotations"))
.methodToReplace(new Hook("com/sun/source/util/Trees", "getTree",
"(Ljavax/lang/model/element/Element;)Lcom/sun/source/tree/Tree;"))
.replacementMethod(new Hook("lombok/netbeans/agent/PatchFixes", "returnNullForGeneratedNode",
"(Lcom/sun/source/util/Trees;Ljavax/lang/model/element/Element;Ljava/lang/Object;)" +
"Lcom/sun/source/tree/Tree;"))
.requestExtra(StackRequest.PARAM1).transplant()
.build());
sm.addScript(ScriptBuilder.replaceMethodCall()
.target(new MethodTarget("org.netbeans.modules.java.source.parsing.FindMethodRegionsVisitor",
"visitMethod"))
.methodToReplace(new Hook("com/sun/source/util/SourcePositions", "getEndPosition",
"(Lcom/sun/source/tree/CompilationUnitTree;Lcom/sun/source/tree/Tree;)J"))
.replacementMethod(new Hook("lombok/netbeans/agent/PatchFixes", "returnMinus1ForGeneratedNode",
"(Lcom/sun/source/util/SourcePositions;Lcom/sun/source/tree/CompilationUnitTree;Lcom/sun/source/tree/Tree;)J"))
.transplant().build());
sm.addScript(ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.netbeans.modules.java.source.save.CasualDiff", "filterHidden"))
.methodToWrap(new Hook("java/lang/Iterable", "iterator", "()L/java/util/Iterator;"))
.wrapMethod(new Hook("lombok/netbeans/agent/PatchFixes", "filterGenerated",
"(Ljava/util/Iterator;)L/java/util/Iterator;"))
.transplant().build());
}
}
@@ -0,0 +1,179 @@
/*
* Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package lombok.netbeans.agent;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import javax.lang.model.element.Element;
import lombok.Lombok;
import lombok.patcher.inject.LiveInjector;
import org.netbeans.Module;
import org.netbeans.ProxyClassLoader;
import org.netbeans.api.java.source.ClasspathInfo;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.TaskListener;
import com.sun.source.util.Trees;
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Context;
// A lot of the footwork on the netbeans support has been done by Jan Lahoda, who is awesome. (jlahoda@netbeans.org)
// This footwork was converted into a patch script form by me (rzwitserloot). See:
// http://code.google.com/p/projectlombok/issues/detail?id=20#c3
public class PatchFixes {
public static boolean loadClass_decision(@SuppressWarnings("unused") ClassLoader loader, String name) throws Exception {
return name.startsWith("lombok.");
}
public static Class<?> loadClass_value(ClassLoader loader, String name) throws Exception {
int last = name.lastIndexOf('.');
String pkg = (last >= 0) ? name.substring(0, last) : "";
Method m = ProxyClassLoader.class.getDeclaredMethod("selfLoadClass", String.class, String.class);
m.setAccessible(true);
return (Class<?>)m.invoke(loader, pkg, name);
}
public static boolean getResource_decision(@SuppressWarnings("unused") ClassLoader loader, String name) throws Exception {
return name.startsWith("META-INF/services/lombok.");
}
public static URL getResource_value(ClassLoader loader, String name) throws Exception {
Method m = ProxyClassLoader.class.getDeclaredMethod("findResource", String.class);
m.setAccessible(true);
return (URL) m.invoke(loader, name);
}
public static boolean getResources_decision(@SuppressWarnings("unused") ClassLoader loader, String name) throws Exception {
return name.startsWith("META-INF/services/lombok.");
}
public static Enumeration<?> getResources_value(ClassLoader loader, String name) throws Exception {
Method m = ProxyClassLoader.class.getDeclaredMethod("findResources", String.class);
m.setAccessible(true);
return (Enumeration<?>) m.invoke(loader, name);
}
public static boolean addSelfToClassLoader(Module module, List<File> classPath) {
if (module.getJarFile().getName().equals("org-netbeans-libs-javacimpl.jar")) {
String lombokJarLoc = LiveInjector.findPathJar(Lombok.class);
classPath.add(new File(lombokJarLoc));
}
return false;
}
public static void fixContentOnSetTaskListener(JavacTaskImpl that, TaskListener taskListener) throws Throwable {
Context context = that.getContext();
if (context.get(TaskListener.class) != null)
context.put(TaskListener.class, (TaskListener)null);
if (taskListener != null) {
try {
Method m = JavacTaskImpl.class.getDeclaredMethod("wrap", TaskListener.class);
try {
m.setAccessible(true);
} catch (SecurityException ignore) {}
TaskListener w = (TaskListener)m.invoke(that, taskListener);
context.put(TaskListener.class, w);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
}
public static Tree returnNullForGeneratedNode(Trees trees, Element element, Object o) throws Throwable {
try {
Tree tree = trees.getTree(element);
if (tree == null) return null;
CompilationUnitTree unit = (CompilationUnitTree) o.getClass().getMethod("getCompilationUnit").invoke(o);
int startPos = (int) trees.getSourcePositions().getStartPosition(unit, tree);
if (startPos == -1) return null;
return tree;
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
public static long returnMinus1ForGeneratedNode(SourcePositions that, CompilationUnitTree cu, Tree tree) {
int start = (int) that.getStartPosition(cu, tree);
if (start < 0) return -1;
return that.getEndPosition(cu, tree);
}
public static void addTaskListenerWhenCallingJavac(JavacTaskImpl task,
@SuppressWarnings("unused") /* Will come in handy later */ ClasspathInfo cpInfo) throws Exception {
Class<?> entryPoint = JavacTaskImpl.class.getClassLoader().loadClass("lombok.netbeans.agent.NetbeansEntryPoint");
task.setTaskListener((TaskListener) entryPoint.getConstructor(Context.class).newInstance(task.getContext()));
}
public static Iterator<JCTree> filterGenerated(final Iterator<JCTree> it) {
return new Iterator<JCTree>() {
private JCTree next;
private boolean hasNext;
{
calc();
}
private void calc() {
while (it.hasNext()) {
JCTree n = it.next();
if (n.pos != -1) {
hasNext = true;
next = n;
return;
}
}
hasNext = false;
next = null;
}
@Override public boolean hasNext() {
return hasNext;
}
@Override public JCTree next() {
if (!hasNext) throw new NoSuchElementException();
JCTree n = next;
calc();
return n;
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
@@ -0,0 +1,26 @@
/*
* Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* Contains the mechanism that instruments netbeans by being loaded as a javaagent.
*/
package lombok.netbeans.agent;