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; } }