package xapi.javac.dev.api;
import com.github.javaparser.ast.plugin.Transformer;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.JavacTask;
import com.sun.tools.javac.api.BasicJavacTask;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.util.Context;
import xapi.dev.processor.AnnotationTools;
import xapi.fu.In1Out1;
import xapi.fu.In2;
import xapi.inject.X_Inject;
import xapi.javac.dev.model.InjectionBinding;
import xapi.javac.dev.model.JavaLibrary;
import xapi.javac.dev.model.XApiInjectionConfiguration;
import xapi.javac.dev.template.TemplateTransformer;
import xapi.source.read.JavaModel;
import xapi.source.read.JavaModel.IsType;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.JavaFileManager;
import java.util.Optional;
/**
* @author James X. Nelson (james@wetheinter.net)
* Created on 3/12/16.
*/
public interface JavacService extends AnnotationTools {
static JavacService instanceFor(JavacTask task) {
if (task instanceof BasicJavacTask) {
return instanceFor(((BasicJavacTask) task).getContext());
}
throw new UnsupportedOperationException("Unable to create javac service from JavacTask " + task);
}
static JavacService instanceFor(Context context) {
JavacService instance = context.get(JavacService.class);
if (instance == null) {
instance = X_Inject.instance(JavacService.class);
context.put(JavacService.class, instance);
}
instance.init(context);
return instance;
}
static JavacService instanceFor(ProcessingEnvironment processingEnv) {
if (processingEnv instanceof JavacProcessingEnvironment) {
final JavacService inst = instanceFor(((JavacProcessingEnvironment) processingEnv).getContext());
inst.remember(Filer.class, processingEnv.getFiler());
return inst;
}
throw new UnsupportedOperationException("Unable to create javac service from processing environment " + processingEnv);
}
String getPackageName(CompilationUnitTree cu);
TypeMirror findType(ExpressionTree init);
void init(Context context);
ClassTree getClassTree(CompilationUnitTree compilationUnit);
Optional<InjectionBinding> getInjectionBinding(XApiInjectionConfiguration config, TypeMirror type);
InjectionBinding createInjectionBinding(VariableTree node);
InjectionBinding createInjectionBinding(MethodTree node);
IsType getInvocationTargetType(CompilationUnitTree cup, MethodInvocationTree node);
JavaModel.IsNamedType getName(CompilationUnitTree cup, MethodInvocationTree node);
ClassTree getEnclosingClass(CompilationUnitTree cup, Tree node);
void readProperties(In2<String, String> in);
<T, C extends Class<T>> T remember(C cls, T value);
<T, C extends Class<T>> T recall(C cls);
default <T, C extends Class<T>> T getOrCreate(C cls, In1Out1<C, T> factory) {
T inst = recall(cls);
if (inst == null) {
inst = factory.io(cls);
remember(cls, inst);
}
return inst;
}
default Transformer getTransformer() {
return getOrCreate(Transformer.class, cls -> new TemplateTransformer());
}
@Override
default JavaFileManager getFileManager() {
return recall(JavaFileManager.class);
}
@Override
default Filer getFiler() {
return recall(Filer.class);
}
default JavaLibrary getJavaLibrary() {
return getOrCreate(JavaLibrary.class, cls -> {
JavaLibrary lib = X_Inject.instance(JavaLibrary.class);
initializeLibrary(lib);
return lib;
});
}
default CompilerService getCompilerService() {
return getOrCreate(CompilerService.class, cls -> CompilerService.compileServiceFrom(this));
}
@Override
default Types getTypes() {
return recall(Types.class);
}
@Override
default Elements getElements() {
return recall(Elements.class);
}
default void initializeLibrary(JavaLibrary lib) {
lib.initialize(this);
}
String getFileName(CompilationUnitTree cup);
String getQualifiedName(CompilationUnitTree cup, ClassTree classTree);
String getQualifiedName(CompilationUnitTree cup, Tree tree);
default String getQualifiedName(CompilationUnitTree cup) {
return getQualifiedName(cup, getClassTree(cup));
}
default SourceTransformationService getSourceTransformService() {
return SourceTransformationService.instanceFrom(this);
}
@Override
default String getPackageName(TypeElement type) {
final PackageElement pkg = getElements().getPackageOf(type);
if (pkg == null) {
return "";
}
return pkg.getQualifiedName().toString();
}
}