package org.jetbrains.plugins.clojure.debugger;
import com.intellij.debugger.engine.evaluation.CodeFragmentFactory;
import com.intellij.debugger.engine.evaluation.TextWithImports;
import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilder;
import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import org.jetbrains.plugins.clojure.debugger.fragments.ClojureCodeFragment;
import org.jetbrains.plugins.clojure.file.ClojureFileType;
import java.util.ArrayList;
import java.util.Collections;
/**
* @author ilyas
*/
public class ClojureCodeFragmentFactory extends CodeFragmentFactory{
public JavaCodeFragment createCodeFragment(TextWithImports item, PsiElement context, Project project) {
final StringBuffer text = new StringBuffer();
final String query = "(do " + StringUtil.escapeStringCharacters(item.getText()) + ")";
ArrayList<String> localNames = getLocalsFromContext(context);
Collections.sort(localNames);
text.append("java.lang.String str = \"(intern 'clojure.core 'tmp-debug (fn [" + StringUtil.join(localNames, " ") + "] " + query + "))\";\n");
text.append("clojure.lang.Compiler.load(new java.io.StringReader(str));\n");
text.append("clojure.lang.Var tmp = clojure.lang.RT.var(\"clojure.core\", \"tmp-debug\");\n");
final String argList = StringUtil.join(localNames, ", ");
text.append("tmp.fn().invoke(" + argList + ");\n");
final JavaCodeFragmentFactory factory = JavaCodeFragmentFactory.getInstance(project);
return factory.createCodeBlockCodeFragment(text.toString(), null, true);
}
private static ArrayList<String> getLocalsFromContext(PsiElement context) {
final ArrayList<String> result = new ArrayList<String>();
if (context instanceof PsiCodeBlock) {
PsiCodeBlock block = (PsiCodeBlock) context;
for (PsiStatement stmt : block.getStatements()) {
if (stmt instanceof PsiDeclarationStatement) {
PsiDeclarationStatement decl = (PsiDeclarationStatement) stmt;
for (PsiElement element : decl.getDeclaredElements()) {
if (element instanceof PsiLocalVariable) {
PsiLocalVariable var = (PsiLocalVariable) element;
result.add(var.getName());
}
}
}
}
}
return result;
}
public JavaCodeFragment createPresentationCodeFragment(TextWithImports item, PsiElement context, Project project) {
final ClojureCodeFragment fragment = new ClojureCodeFragment(project, item.getText());
fragment.setContext(context);
return fragment;
}
public boolean isContextAccepted(PsiElement context) {
return context != null && context.getLanguage().equals(ClojureFileType.CLOJURE_FILE_TYPE.getLanguage());
}
public LanguageFileType getFileType() {
return ClojureFileType.CLOJURE_FILE_TYPE;
}
public EvaluatorBuilder getEvaluatorBuilder() {
return EvaluatorBuilderImpl.getInstance();
}
}