package jetbrains.mps.debugger.java.runtime.evaluation.container;
/*Generated by MPS */
import org.jetbrains.annotations.Nullable;
import jetbrains.mps.project.Project;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.debugger.java.api.evaluation.EvaluationException;
import jetbrains.mps.make.IMakeService;
import jetbrains.mps.make.MakeSession;
import jetbrains.mps.ide.make.DefaultMakeMessageHandler;
import jetbrains.mps.make.script.IScript;
import jetbrains.mps.make.script.ScriptBuilder;
import jetbrains.mps.make.facet.IFacet;
import jetbrains.mps.make.facet.ITarget;
import jetbrains.mps.make.script.IResult;
import jetbrains.mps.smodel.resources.ModelsToResources;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.compiler.EclipseJavaCompiler;
import jetbrains.mps.smodel.resources.FResource;
import java.util.Map;
import jetbrains.mps.internal.collections.runtime.MapSequence;
import jetbrains.mps.text.TextUnit;
import jetbrains.mps.compiler.JavaCompilerOptions;
import jetbrains.mps.compiler.JavaCompilerOptionsComponent;
import jetbrains.mps.baseLanguage.closures.runtime.Wrappers;
import java.util.Set;
import jetbrains.mps.project.facets.JavaModuleOperations;
import jetbrains.mps.util.SNodeOperations;
import java.util.concurrent.ExecutionException;
import java.lang.reflect.InvocationTargetException;
import jetbrains.mps.debugger.java.api.evaluation.InvocationTargetEvaluationException;
import jetbrains.mps.compiler.CompilationResultAdapter;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
public class GeneratorUtil {
@Nullable
public static Class generateAndLoadEvaluatorClass(Project project, final SModel model, String className, boolean developerMode, ClassLoader parentloader) throws EvaluationException {
IMakeService makeService = IMakeService.INSTANCE.get();
MakeSession makeSession = new MakeSession(project, new DefaultMakeMessageHandler(project), false);
if (makeService.openNewSession(makeSession)) {
try {
IScript script = new ScriptBuilder().withFacetNames(new IFacet.Name("jetbrains.mps.lang.core.Generate"), new IFacet.Name("jetbrains.mps.lang.core.TextGen"), new IFacet.Name("jetbrains.mps.debugger.java.evaluation.JavaDebugEvaluate"), new IFacet.Name("jetbrains.mps.make.facets.Make")).withFinalTarget(new ITarget.Name("jetbrains.mps.lang.core.TextGen.textGenToMemory")).toScript();
IResult result = makeService.make(makeSession, new ModelsToResources(Sequence.<SModel>singleton(model)).resources(false), script).get();
boolean successful = result.isSucessful();
String source = null;
final String desiredSourceUnitName = className + ".java";
if (successful) {
EclipseJavaCompiler javaCompiler = new EclipseJavaCompiler();
for (FResource res : Sequence.fromIterable(result.output()).ofType(FResource.class)) {
Map<String, Object> contents = res.contents();
for (String unitName : MapSequence.fromMap(contents).keySet()) {
if (!(unitName.endsWith(".java"))) {
continue;
}
Object textGenOutcome = MapSequence.fromMap(contents).get(unitName);
if (textGenOutcome instanceof TextUnit) {
TextUnit tu = (TextUnit) textGenOutcome;
source = new String(tu.getBytes(), tu.getEncoding());
} else {
// FIXME fallback, shall not happen with textGenToMemory using new j.m.text API
source = String.valueOf(textGenOutcome);
}
javaCompiler.addSource(res.packageName() + '.' + unitName.substring(0, unitName.length() - 5), source);
if (unitName.equals(desiredSourceUnitName)) {
// FIXME WTF? why unit name is treated as source, and do we really need to keep source at all?
source = String.valueOf(unitName);
}
}
}
GeneratorUtil.MyCompilationResultAdapter compilationResult = new GeneratorUtil.MyCompilationResultAdapter();
javaCompiler.addCompilationResultListener(compilationResult);
JavaCompilerOptions options = null;
if (project != null) {
options = JavaCompilerOptionsComponent.getInstance().getJavaCompilerOptions(project);
}
final Wrappers._T<Set<String>> collectCompileClasspath = new Wrappers._T<Set<String>>(null);
project.getModelAccess().runReadAction(new Runnable() {
public void run() {
collectCompileClasspath.value = JavaModuleOperations.collectCompileClasspath(model.getModule());
}
});
javaCompiler.compile(JavaModuleOperations.createClassPathItem(collectCompileClasspath.value, GeneratorUtil.class.getName()), (options != null ? options : JavaCompilerOptionsComponent.DEFAULT_JAVA_COMPILER_OPTIONS));
javaCompiler.removeCompilationResultListener(compilationResult);
final String fullClassName = SNodeOperations.getModelLongName(model) + "." + className;
if (successful && (source != null && source.length() > 0)) {
if (developerMode) {
System.err.println("[Generated text]\n" + source + "\n[Generated text]");
}
return Class.forName(fullClassName, true, javaCompiler.getClassLoader(parentloader));
} else if ((source != null && source.length() > 0) && !(successful)) {
String text = "Errors during compilation";
if (compilationResult.hasErrors()) {
text += ":\n" + compilationResult.getMessage();
} else {
text += ".";
}
throw new EvaluationException(text);
}
}
// else fall-through, up to throws EvaluationException below
} catch (InterruptedException e) {
throw new EvaluationException(e);
} catch (ExecutionException e) {
throw new EvaluationException(e);
} catch (ClassNotFoundException e) {
throw new EvaluationException(e);
}
}
throw new EvaluationException("Errors during generation.");
}
public static <E> E createInstance(Class clazz, Class[] parameterClasses, Object[] parameters) throws EvaluationException {
try {
return (E) clazz.getConstructor(parameterClasses).newInstance(parameters);
} catch (InvocationTargetException e) {
throw new InvocationTargetEvaluationException(e.getCause());
} catch (NoSuchMethodException e) {
throw new EvaluationException(e);
} catch (IllegalAccessException e) {
throw new EvaluationException(e);
} catch (InstantiationException e) {
throw new EvaluationException(e);
}
}
private static class MyCompilationResultAdapter extends CompilationResultAdapter {
private final StringBuffer myBuffer = new StringBuffer();
private boolean myHasErrors;
public MyCompilationResultAdapter() {
}
@Override
public void onCompilationResult(CompilationResult result) {
if (result.hasErrors()) {
myHasErrors = true;
for (CategorizedProblem error : result.getErrors()) {
myBuffer.append(error.getMessage());
myBuffer.append("\n");
}
}
}
public boolean hasErrors() {
return myHasErrors;
}
public String getMessage() {
return myBuffer.toString();
}
}
}