package jetbrains.mps.ide.platform.actions;
/*Generated by MPS */
import com.intellij.execution.filters.Filter;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.openapi.module.SRepository;
import jetbrains.mps.ide.project.ProjectHelper;
import java.util.Iterator;
import jetbrains.mps.textgen.trace.DebugInfo;
import jetbrains.mps.textgen.trace.DefaultTraceInfoProvider;
import jetbrains.mps.util.NameUtil;
import org.jetbrains.mps.openapi.model.SNodeReference;
import jetbrains.mps.textgen.trace.BaseLanguageNodeLookup;
import com.intellij.execution.filters.HyperlinkInfo;
import jetbrains.mps.project.MPSProject;
import jetbrains.mps.ide.navigation.NodeNavigatable;
public class MPSStackTraceFilter implements Filter {
private static String STRING_START = "at ";
protected final Project myProject;
public MPSStackTraceFilter(Project project) {
myProject = project;
}
@Nullable
@Override
public Filter.Result applyFilter(String line, int length) {
return tryToParseLine(line, length - line.length());
}
private Filter.Result tryToParseLine(String line, int offset) {
if (((line == null ? null : line.trim())).indexOf(STRING_START) < 0) {
return null;
}
int start = line.indexOf(STRING_START) + STRING_START.length();
String tmpStr = line.substring(start);
int parenIndex = tmpStr.indexOf("(");
if (parenIndex == -1) {
return null;
}
final String methodName = tmpStr.substring(0, parenIndex);
int closingParenIndex = tmpStr.indexOf(")");
if (closingParenIndex == -1) {
return null;
}
final String position = tmpStr.substring(parenIndex + 1, closingParenIndex);
int lastDot = methodName.lastIndexOf(".");
final String unitName = ((lastDot == -1 ? "" : methodName.substring(0, lastDot)));
String[] split = position.split(":");
if (split.length < 2) {
return null;
}
final String fileName = split[0];
final int lineNumber;
try {
lineNumber = Integer.parseInt(split[1]);
} catch (NumberFormatException e) {
return null;
}
int hlStart = start + parenIndex + 1 + offset;
int hlEnd = start + closingParenIndex + offset;
return detectTarget(hlStart, hlEnd, unitName, fileName, lineNumber);
}
protected Filter.Result detectTarget(int hlStart, int hlEnd, final String unitName, final String fileName, final int lineNumber) {
SRepository repo = ProjectHelper.getProjectRepository(myProject);
if (repo == null) {
return null;
}
for (Iterator<DebugInfo> it = new DefaultTraceInfoProvider(repo).debugInfo(NameUtil.namespaceFromLongName(unitName)).iterator(); it.hasNext();) {
final SNodeReference n = new BaseLanguageNodeLookup(it.next()).getNodeAt(fileName, lineNumber);
if (n == null) {
continue;
}
// XXX could benefit from repo.isAccessible(SNodeReference) that finds out whether reference could be resolved but doesn't provide node and thus doesn't require external model access
// though takes one internally to find out
return new Filter.Result(hlStart, hlEnd, new HyperlinkInfo() {
@Override
public void navigate(Project ideaProject) {
MPSProject mpsProject = ProjectHelper.fromIdeaProject(ideaProject);
if (mpsProject != null) {
new NodeNavigatable(mpsProject, n).navigate(true);
}
}
});
}
return null;
}
}