Navigatable (@NotNull Location<?> location, @NotNull String stacktrace) { final PsiLocation<?> psiLocation = location.toPsiLocation(); PsiClass containingClass = psiLocation.getParentElement(PsiClass.class); if (containingClass == null && location instanceof MethodLocation) { containingClass = ((MethodLocation)location).getContainingClass(); } if (containingClass == null) return null; final String qualifiedName = containingClass.getQualifiedName(); if (qualifiedName == null) return null; PsiMethod containingMethod = null; for (Iterator<Location<PsiMethod>> iterator = psiLocation.getAncestors(PsiMethod.class, false); iterator.hasNext();) { final PsiMethod psiMethod = iterator.next().getPsiElement(); if (containingClass.equals(psiMethod.getContainingClass())) containingMethod = psiMethod; } if (containingMethod == null) return null; String methodName = containingMethod.getName(); StackTraceLine lastLine = null; final String[] stackTrace = new LineTokenizer(stacktrace).execute(); for (String aStackTrace : stackTrace) { final StackTraceLine line = new StackTraceLine(containingClass.getProject(), aStackTrace); if (methodName.equals(line.getMethodName()) && qualifiedName.equals(line.getClassName())) { lastLine = line; break; } } if (lastLine != null) { try { int lineNumber = lastLine.getLineNumber(); PsiFile psiFile = containingClass.getContainingFile(); Document document = PsiDocumentManager.getInstance(containingClass.getProject()).getDocument(psiFile); TextRange textRange = containingMethod.getTextRange(); if (textRange == null || document == null || lineNumber >= 0 && lineNumber < document.getLineCount() && textRange.contains(document.getLineStartOffset(lineNumber))) { return new OpenFileDescriptor(containingClass.getProject(), psiFile.getVirtualFile(), lineNumber, 0); } } catch (NumberFormatException ignored) { } } return null; }