aptIn16/core/src/main/java/com/moparisthebest/mirror/apt/ConvertAnnotationProcessorF...

215 lines
7.7 KiB
Java
Executable File

/*
* aptIn16 - Apt implementation with Java 6 annotation processors.
* Copyright (C) 2012 Travis Burtrum (moparisthebest)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published y
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.moparisthebest.mirror.apt;
import com.moparisthebest.mirror.convert.Convertable;
import com.moparisthebest.mirror.declaration.ConvertDeclaration;
import com.sun.mirror.apt.AnnotationProcessorFactory;
import com.sun.mirror.declaration.AnnotationTypeDeclaration;
import com.moparisthebest.mirror.log.Debug;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.*;
public class ConvertAnnotationProcessorFactory implements Processor {
public static final boolean debug = false;
static {
String command = System.getProperty("sun.java.command");
// hack to stop IDEA from permanently freezing when processing annotations
// todo: please tell me why, for the life of me I can't figure it out...
if (command != null && command.startsWith("com.intellij.rt.compiler")) {
// command looks like: com.intellij.rt.compiler.JavacRunner java version 1.6.0_30 com.sun.tools.javac.Main [options]
System.setOut(System.err);
System.err.println("INFO: activated IDEA hack of re-directing System.out to System.err");
}
PrintStream oldOut = System.out;
if ((debug || System.getProperty("aptin16.debug") != null))
try {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("/aptin16.log");
} catch (Exception e) {
fos = new FileOutputStream(System.getProperty("user.home") + "/aptin16.log");
}
PrintStream out = new PrintStream(fos, true);
System.setOut(out);
System.setErr(out);
System.out.println(new Date() + ": log successfully set!");
System.out.printf("oldOut: '%s' class: '%s'\n", oldOut.toString(), oldOut.getClass().toString());
} catch (Exception e) {
e.printStackTrace();
}
}
private final AnnotationProcessorFactory internal;
// at least for now, all of the ProcessingEnvironment's multiple instances get sent
// are the EXACT same object, so we might as well make this static and save some time
protected static ConvertAnnotationProcessorEnvironment env = null;
public ConvertAnnotationProcessorFactory(String annotationProcessorFactoryName) {
AnnotationProcessorFactory internal = null;
try {
internal = (AnnotationProcessorFactory) Class.forName(annotationProcessorFactoryName).newInstance();
System.out.println("ConvertAnnotationProcessorFactory running " + internal.getClass().getName());
} catch (Throwable e) {
System.out.printf("Not running AnnotationProcessorFactory '%s' because of error!\n", annotationProcessorFactoryName);
e.printStackTrace();
}
this.internal = internal;
}
public ConvertAnnotationProcessorFactory(AnnotationProcessorFactory internal) {
if (internal == null)
throw new NullPointerException("AnnotationProcessorFactory cannot be null!");
System.out.println("ConvertAnnotationProcessorFactory running " + internal.getClass().getName());
this.internal = internal;
}
public static Set<String> cleanOptions(Collection<String> input) {
Set<String> ret = new LinkedHashSet<String>(input.size());
for (String option : input)
ret.add(option.replaceFirst("^-A", "")); // have to strip -A from beginning of options...
if (Debug.debug)
System.out.println("supportedOptions: " + ret);
return ret;
}
@Override
public Set<String> getSupportedOptions() {
return cleanOptions(internal.supportedOptions());
}
@Override
public Set<String> getSupportedAnnotationTypes() {
if (Debug.debug)
System.out.printf("factory: '%s' supportedAnnotationTypes: '%s'\n", internal.getClass().getName(), internal.supportedAnnotationTypes());
return Convertable.toSet(internal.supportedAnnotationTypes());
}
private static synchronized void staticInit(ProcessingEnvironment processingEnv) {
if (env != null)
return;
env = new ConvertAnnotationProcessorEnvironment(processingEnv);
/*
// the following helps us debug, since I know no way of debugging in javac itself
System.setOut(
new PrintStream(System.out) {
public static final byte debugLevel = 90;
public void printInfo() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
int x = 2; // start at 3
printStackTrace(stackTrace[x], "", "");
int level = x + debugLevel;
StringBuilder tabs = new StringBuilder();
while (++x < level && x < stackTrace.length)
printStackTrace(stackTrace[x], "Called", tabs.append('\t').toString());
}
private void printStackTrace(StackTraceElement ste, String msg, String returnType) {
super.printf("%s%s.%s(%s:%d) %s\n",
returnType,
//ste.getClassName().replaceFirst(".*\\.", "")
ste.getClassName()
, ste.getMethodName(),
ste.getFileName(), ste.getLineNumber(),
msg);
}
@Override
public void println(String x) {
printInfo();
super.println(x);
}
}
);
System.setErr(System.out);
//System.err.println("woohoo! quitting!");
//System.exit(0);
*/
}
@Override
public void init(ProcessingEnvironment processingEnv) {
//env = new ConvertAnnotationProcessorEnvironment(processingEnv); // if we change it back to an instance variable
staticInit(processingEnv);
}
/**
* @param annotations
* @param roundEnv
* @return
*/
@Override
public synchronized boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
env.getFiler().setModified(false);
env.setRoundEnv(roundEnv);
internal.getProcessorFor(ConvertDeclaration.getConvertable().convertToSet(annotations, AnnotationTypeDeclaration.class), env).process();
return env.getFiler().isModified(); //todo: don't know what to return here
//return true;
//return false; // apt didn't return anything or have a notion of 'claiming' annotations, but false breaks beehive...
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
@Override
public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
return Collections.emptyList();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o instanceof AnnotationProcessorFactory) return internal.equals(o);
if (o == null || getClass() != o.getClass()) return false;
ConvertAnnotationProcessorFactory that = (ConvertAnnotationProcessorFactory) o;
return internal.equals(that.internal);
}
@Override
public int hashCode() {
return internal.hashCode();
}
@Override
public String toString() {
return internal.toString();
}
}