aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoel Spilker <r.spilker@gmail.com>2010-08-03 03:41:07 +0200
committerRoel Spilker <r.spilker@gmail.com>2010-08-03 03:41:07 +0200
commit57bb88a7691dd89029517a79393a62e6cdedc3ce (patch)
tree37fb6bf42eae92064eeca6d8736b1cd91215f72f
parent40466c3e2d7d26a43b58f008986fd0b84c986b27 (diff)
downloadlombok-57bb88a7691dd89029517a79393a62e6cdedc3ce.tar.gz
lombok-57bb88a7691dd89029517a79393a62e6cdedc3ce.tar.bz2
lombok-57bb88a7691dd89029517a79393a62e6cdedc3ce.zip
Post Compiler now works, including the sneaky throws remover. Also added a lombok app for it. Not yet in eclipse, though
-rw-r--r--src/core/lombok/bytecode/PostCompilerApp.java152
-rw-r--r--src/core/lombok/bytecode/SneakyThrowsRemover.java66
-rw-r--r--src/core/lombok/core/PostCompiler.java14
-rw-r--r--src/core/lombok/core/PostCompilerTransformation.java21
4 files changed, 222 insertions, 31 deletions
diff --git a/src/core/lombok/bytecode/PostCompilerApp.java b/src/core/lombok/bytecode/PostCompilerApp.java
new file mode 100644
index 00000000..3a413d67
--- /dev/null
+++ b/src/core/lombok/bytecode/PostCompilerApp.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright © 2010 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.bytecode;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import lombok.core.DiagnosticsReceiver;
+import lombok.core.LombokApp;
+import lombok.core.PostCompiler;
+
+import org.mangosdk.spi.ProviderFor;
+
+import com.zwitserloot.cmdreader.CmdReader;
+import com.zwitserloot.cmdreader.Description;
+import com.zwitserloot.cmdreader.InvalidCommandLineException;
+import com.zwitserloot.cmdreader.Mandatory;
+import com.zwitserloot.cmdreader.Sequential;
+import com.zwitserloot.cmdreader.Shorthand;
+
+@ProviderFor(LombokApp.class)
+public class PostCompilerApp implements LombokApp {
+ @Override public List<String> getAppAliases() {
+ return Arrays.asList("post", "postcompile");
+ }
+
+ @Override public String getAppDescription() {
+ return "Runs registered post compiler handlers to against existing class files, modifying them in the process.";
+ }
+
+ @Override public String getAppName() {
+ return "post-compile";
+ }
+
+ public static class CmdArgs {
+ @Sequential
+ @Mandatory
+ @Description("paths to class files to be converted. If a directory is named, all files (recursively) in that directory will be converted.")
+ private List<String> classFiles = new ArrayList<String>();
+
+ @Shorthand("v")
+ @Description("Prints lots of status information as the post compiler runs")
+ boolean verbose = false;
+
+ @Shorthand({"h", "?"})
+ @Description("Shows this help text")
+ boolean help = false;
+ }
+
+ @Override public int runApp(List<String> raw) throws Exception {
+ CmdReader<CmdArgs> reader = CmdReader.of(CmdArgs.class);
+ CmdArgs args;
+ try {
+ args = reader.make(raw.toArray(new String[0]));
+ if (args.help) {
+ System.out.println(reader.generateCommandLineHelp("java -jar lombok.jar post-compile"));
+ return 0;
+ }
+ } catch (InvalidCommandLineException e) {
+ System.err.println(e.getMessage());
+ System.err.println(reader.generateCommandLineHelp("java -jar lombok.jar post-compile"));
+ return 1;
+ }
+
+ List<File> filesToProcess = new ArrayList<File>();
+ for (String f : args.classFiles) addFiles(filesToProcess, f);
+
+ int filesVisited = 0, filesTouched = 0;
+ for (File file : filesToProcess) {
+ if (!file.exists() || !file.isFile()) {
+ System.out.printf("Cannot find file '%s'\n", file);
+ continue;
+ }
+ filesVisited++;
+ if (args.verbose) System.out.println("Processing " + file.getAbsolutePath());
+ byte[] original = readFile(file);
+ byte[] clone = original.clone();
+ byte[] transformed = PostCompiler.applyTransformations(clone, file.toString(), DiagnosticsReceiver.CONSOLE);
+ if (clone != transformed && !Arrays.equals(clone, transformed)) {
+ filesTouched++;
+ if (args.verbose) System.out.println("Rewriting " + file.getAbsolutePath());
+ writeFile(file, transformed);
+ }
+ }
+
+ if (args.verbose) {
+ System.out.printf("Total files visited: %d total files changed: %d\n", filesVisited, filesTouched);
+ }
+
+ return filesVisited == 0 ? 1 : 0;
+ }
+
+ private void addFiles(List<File> filesToProcess, String f) {
+ File file = new File(f);
+ if (file.isDirectory()) {
+ addRecursively(filesToProcess, file);
+ } else {
+ filesToProcess.add(file);
+ }
+ }
+
+ private void addRecursively(List<File> filesToProcess, File file) {
+ for (File f : file.listFiles()) {
+ if (f.isDirectory()) addRecursively(filesToProcess, f);
+ else if (f.getName().endsWith(".class")) filesToProcess.add(f);
+ }
+ }
+
+ private static byte[] readFile(File file) throws IOException {
+ byte[] buffer = new byte[1024];
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ FileInputStream fileInputStream = new FileInputStream(file);
+ while (true) {
+ int read = fileInputStream.read(buffer);
+ if (read == -1) break;
+ bytes.write(buffer, 0, read);
+ }
+ fileInputStream.close();
+ return bytes.toByteArray();
+ }
+
+ private static void writeFile(File file, byte[] transformed) throws IOException {
+ FileOutputStream out = new FileOutputStream(file);
+ out.write(transformed);
+ out.close();
+ }
+}
diff --git a/src/core/lombok/bytecode/SneakyThrowsRemover.java b/src/core/lombok/bytecode/SneakyThrowsRemover.java
index b816cd54..02a220c3 100644
--- a/src/core/lombok/bytecode/SneakyThrowsRemover.java
+++ b/src/core/lombok/bytecode/SneakyThrowsRemover.java
@@ -1,5 +1,28 @@
+/*
+ * Copyright © 2010 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.bytecode;
+import java.util.concurrent.atomic.AtomicBoolean;
+
import lombok.core.DiagnosticsReceiver;
import lombok.core.PostCompilerTransformation;
@@ -51,30 +74,33 @@ public class SneakyThrowsRemover implements PostCompilerTransformation {
ClassReader reader = new ClassReader(fixedByteCode);
ClassWriter writer = new FixedClassWriter(reader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
+ final AtomicBoolean changesMade = new AtomicBoolean();
+
+ class SneakyThrowsRemoverVisitor extends MethodAdapter {
+ SneakyThrowsRemoverVisitor(MethodVisitor mv) {
+ super(mv);
+ }
+
+ @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ boolean hit = true;
+ if (hit && opcode != Opcodes.INVOKESTATIC) hit = false;
+ if (hit && !"sneakyThrow".equals(name)) hit = false;
+ if (hit && !"lombok/Lombok".equals(owner)) hit = false;
+ if (hit && !"(Ljava/lang/Throwable;)Ljava/lang/RuntimeException;".equals(desc)) hit = false;
+ if (hit) {
+ changesMade.set(true);
+ super.visitInsn(Opcodes.ATHROW);
+ } else {
+ super.visitMethodInsn(opcode, owner, name, desc);
+ }
+ }
+ }
+
reader.accept(new ClassAdapter(writer) {
@Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
return new SneakyThrowsRemoverVisitor(super.visitMethod(access, name, desc, signature, exceptions));
}
}, 0);
- return writer.toByteArray();
- }
-
- private class SneakyThrowsRemoverVisitor extends MethodAdapter {
- SneakyThrowsRemoverVisitor(MethodVisitor mv) {
- super(mv);
- }
-
- @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) {
- boolean hit = true;
- if (hit && opcode != Opcodes.INVOKESTATIC) hit = false;
- if (hit && !"sneakyThrow".equals(name)) hit = false;
- if (hit && !"lombok/Lombok".equals(owner)) hit = false;
- if (hit && !"(Ljava/lang/Throwable;)Ljava/lang/RuntimeException;".equals(desc)) hit = false;
- if (hit) {
- super.visitInsn(Opcodes.ATHROW);
- } else {
- super.visitMethodInsn(opcode, owner, name, desc);
- }
- }
+ return changesMade.get() ? writer.toByteArray() : null;
}
}
diff --git a/src/core/lombok/core/PostCompiler.java b/src/core/lombok/core/PostCompiler.java
index a473b45f..07cfc04d 100644
--- a/src/core/lombok/core/PostCompiler.java
+++ b/src/core/lombok/core/PostCompiler.java
@@ -22,8 +22,7 @@
package lombok.core;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.Collections;
import java.util.List;
public final class PostCompiler {
@@ -49,17 +48,10 @@ public final class PostCompiler {
private static synchronized void init(DiagnosticsReceiver diagnostics) {
if (transformations != null) return;
- transformations = new ArrayList<PostCompilerTransformation>();
try {
- Iterator<PostCompilerTransformation> discovered = SpiLoadUtil.findServices(PostCompilerTransformation.class).iterator();
- while (discovered.hasNext()) {
- try {
- transformations.add(discovered.next());
- } catch (Exception e) {
- diagnostics.addWarning("Error during loading post-compile transformers: " + e.getMessage());
- }
- }
+ transformations = SpiLoadUtil.readAllFromIterator(SpiLoadUtil.findServices(PostCompilerTransformation.class, PostCompilerTransformation.class.getClassLoader()));
} catch (IOException e) {
+ transformations = Collections.emptyList();
diagnostics.addWarning("Could not load post-compile transformers: " + e.getMessage());
}
}
diff --git a/src/core/lombok/core/PostCompilerTransformation.java b/src/core/lombok/core/PostCompilerTransformation.java
index c174b97f..e0770f53 100644
--- a/src/core/lombok/core/PostCompilerTransformation.java
+++ b/src/core/lombok/core/PostCompilerTransformation.java
@@ -1,3 +1,24 @@
+/*
+ * Copyright © 2010 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;
public interface PostCompilerTransformation {