cache classes and files in console exception filter

This commit is contained in:
peter
2014-02-04 15:27:16 +01:00
parent 0898580c85
commit 906efb7909
5 changed files with 116 additions and 55 deletions
@@ -39,16 +39,17 @@ import java.util.Map;
* @author gregsh
*/
public class ExceptionExFilterFactory implements ExceptionFilterFactory {
@NotNull
@Override
public Filter create(GlobalSearchScope searchScope) {
public Filter create(@NotNull GlobalSearchScope searchScope) {
return new MyFilter(searchScope);
}
private static class MyFilter implements Filter, FilterMixin {
private final GlobalSearchScope myScope;
private final ExceptionInfoCache myCache;
public MyFilter(@NotNull final GlobalSearchScope scope) {
myScope = scope;
myCache = new ExceptionInfoCache(scope);
}
public Result applyFilter(final String line, final int textEndOffset) {
@@ -68,7 +69,7 @@ public class ExceptionExFilterFactory implements ExceptionFilterFactory {
Map<String, Trinity<TextRange, TextRange, TextRange>> visited = new THashMap<String, Trinity<TextRange, TextRange, TextRange>>();
final Trinity<TextRange, TextRange, TextRange> emptyInfo = Trinity.create(null, null, null);
final ExceptionWorker worker = new ExceptionWorker(myScope.getProject(), myScope);
final ExceptionWorker worker = new ExceptionWorker(myCache);
for (int i = 0; i < copiedFragment.getLineCount(); i++) {
final int lineStartOffset = copiedFragment.getLineStartOffset(i);
final int lineEndOffset = copiedFragment.getLineEndOffset(i);
@@ -20,14 +20,14 @@ import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
public class ExceptionFilter implements Filter, DumbAware {
private final GlobalSearchScope myScope;
private final ExceptionInfoCache myCache;
public ExceptionFilter(@NotNull final GlobalSearchScope scope) {
myScope = scope;
myCache = new ExceptionInfoCache(scope);
}
public Result applyFilter(final String line, final int textEndOffset) {
ExceptionWorker worker = new ExceptionWorker(myScope.getProject(), myScope);
ExceptionWorker worker = new ExceptionWorker(myCache);
worker.execute(line, textEndOffset);
return worker.getResult();
}
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.vcs.contentAnnotation;
import com.intellij.execution.filters.ExceptionInfoCache;
import com.intellij.execution.filters.ExceptionWorker;
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.FilterMixin;
@@ -54,15 +55,15 @@ import java.util.*;
public class VcsContentAnnotationExceptionFilter implements Filter, FilterMixin {
private final Project myProject;
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.contentAnnotation.VcsContentAnnotationExceptionFilter");
private final GlobalSearchScope myScope;
private final VcsContentAnnotationSettings mySettings;
private Map<VirtualFile,VcsRevisionNumber> myRevNumbersCache;
private final Map<VirtualFile,VcsRevisionNumber> myRevNumbersCache;
private final ExceptionInfoCache myCache;
public VcsContentAnnotationExceptionFilter(@NotNull GlobalSearchScope scope) {
myScope = scope;
myProject = scope.getProject();
mySettings = VcsContentAnnotationSettings.getInstance(myProject);
myRevNumbersCache = new HashMap<VirtualFile, VcsRevisionNumber>();
myCache = new ExceptionInfoCache(scope);
}
private static class MyAdditionalHighlight extends AdditionalHighlight {
@@ -75,10 +76,10 @@ public class VcsContentAnnotationExceptionFilter implements Filter, FilterMixin
EditorColorsScheme globalScheme = EditorColorsManager.getInstance().getGlobalScheme();
final TextAttributes changedColor = globalScheme.getAttributes(DiffColors.DIFF_MODIFIED);
if (source == null) {
TextAttributes atts =
TextAttributes attrs =
globalScheme.getAttributes(CodeInsightColors.CLASS_NAME_ATTRIBUTES).clone();
atts.setBackgroundColor(changedColor.getBackgroundColor());
return atts;
attrs.setBackgroundColor(changedColor.getBackgroundColor());
return attrs;
}
TextAttributes clone = source.clone();
clone.setBackgroundColor(changedColor.getBackgroundColor());
@@ -103,7 +104,7 @@ public class VcsContentAnnotationExceptionFilter implements Filter, FilterMixin
for (int i = 0; i < copiedFragment.getLineCount(); i++) {
final int lineStartOffset = copiedFragment.getLineStartOffset(i);
final int lineEndOffset = copiedFragment.getLineEndOffset(i);
final ExceptionWorker worker = new ExceptionWorker(myProject, myScope);
final ExceptionWorker worker = new ExceptionWorker(myCache);
final String[] lineText = new String[1];
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
@@ -216,7 +217,7 @@ public class VcsContentAnnotationExceptionFilter implements Filter, FilterMixin
}
}
private Document getDocumentForFile(final ExceptionWorker worker) {
private static Document getDocumentForFile(final ExceptionWorker worker) {
return ApplicationManager.getApplication().runReadAction(new Computable<Document>() {
@Override
public Document compute() {
@@ -231,7 +232,9 @@ public class VcsContentAnnotationExceptionFilter implements Filter, FilterMixin
}
// line numbers
private List<TextRange> findMethodRange(final ExceptionWorker worker, final Document document, final Trinity<PsiClass, PsiFile, String> previousLineResult) {
private static List<TextRange> findMethodRange(final ExceptionWorker worker,
final Document document,
final Trinity<PsiClass, PsiFile, String> previousLineResult) {
return ApplicationManager.getApplication().runReadAction(new Computable<List<TextRange>>() {
@Override
public List<TextRange> compute() {
@@ -249,7 +252,7 @@ public class VcsContentAnnotationExceptionFilter implements Filter, FilterMixin
// null - check all
@Nullable
private List<PsiMethod> selectMethod(final PsiMethod[] methods, final Trinity<PsiClass, PsiFile, String> previousLineResult) {
private static List<PsiMethod> selectMethod(final PsiMethod[] methods, final Trinity<PsiClass, PsiFile, String> previousLineResult) {
if (previousLineResult == null || previousLineResult.getThird() == null) return null;
final List<PsiMethod> result = new SmartList<PsiMethod>();
@@ -270,7 +273,7 @@ public class VcsContentAnnotationExceptionFilter implements Filter, FilterMixin
return result;
}
private List<TextRange> getTextRangeForMethod(final ExceptionWorker worker, Trinity<PsiClass, PsiFile, String> previousLineResult) {
private static List<TextRange> getTextRangeForMethod(final ExceptionWorker worker, Trinity<PsiClass, PsiFile, String> previousLineResult) {
String method = worker.getMethod();
PsiClass psiClass = worker.getPsiClass();
PsiMethod[] methods;
@@ -0,0 +1,79 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.execution.filters;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.reference.SoftReference;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.ConcurrentMap;
/**
* @author peter
*/
public class ExceptionInfoCache {
private final ConcurrentMap<String, SoftReference<Pair<PsiClass[], PsiFile[]>>> myCache = ContainerUtil.newConcurrentMap();
private final Project myProject;
private final GlobalSearchScope mySearchScope;
public ExceptionInfoCache(GlobalSearchScope searchScope) {
myProject = ObjectUtils.assertNotNull(searchScope.getProject());
mySearchScope = searchScope;
}
@NotNull public Project getProject() {
return myProject;
}
@NotNull
private PsiClass[] findClassesPreferringMyScope(String className) {
JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(myProject);
PsiClass[] result = psiFacade.findClasses(className, mySearchScope);
return result.length != 0 ? result : psiFacade.findClasses(className, GlobalSearchScope.allScope(myProject));
}
Pair<PsiClass[], PsiFile[]> resolveClass(String className) {
Pair<PsiClass[], PsiFile[]> cached = SoftReference.dereference(myCache.get(className));
if (cached != null) {
return cached;
}
PsiClass[] classes = findClassesPreferringMyScope(className);
if (classes.length == 0) {
final int dollarIndex = className.indexOf('$');
if (dollarIndex >= 0) {
classes = findClassesPreferringMyScope(className.substring(0, dollarIndex));
}
}
PsiFile[] files = new PsiFile[classes.length];
for (int i = 0; i < classes.length; i++) {
files[i] = (PsiFile)classes[i].getContainingFile().getNavigationElement();
}
Pair<PsiClass[], PsiFile[]> result = Pair.create(classes, files);
myCache.put(className, new SoftReference<Pair<PsiClass[], PsiFile[]>>(result));
return result;
}
}
@@ -21,13 +21,12 @@ import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ui.UIUtil;
@@ -62,16 +61,16 @@ public class ExceptionWorker {
}
private final Project myProject;
private final GlobalSearchScope mySearchScope;
private Filter.Result myResult;
private PsiClass[] myClasses = PsiClass.EMPTY_ARRAY;
private PsiFile[] myFiles = PsiFile.EMPTY_ARRAY;
private String myMethod;
private Trinity<TextRange, TextRange, TextRange> myInfo;
private final ExceptionInfoCache myCache;
public ExceptionWorker(@NotNull Project project, @NotNull GlobalSearchScope searchScope) {
myProject = project;
mySearchScope = searchScope;
public ExceptionWorker(@NotNull ExceptionInfoCache cache) {
myProject = cache.getProject();
myCache = cache;
}
public void execute(final String line, final int textEndOffset) {
@@ -93,11 +92,9 @@ public class ExceptionWorker {
final String lineString = fileAndLine.substring(colonIndex + 1);
try {
final int lineNumber = Integer.parseInt(lineString);
myClasses = findPositionClasses(line);
myFiles = new PsiFile[myClasses.length];
for (int i = 0; i < myClasses.length; i++) {
myFiles[i] = (PsiFile)myClasses[i].getContainingFile().getNavigationElement();
}
Pair<PsiClass[], PsiFile[]> pair = myCache.resolveClass(myInfo.first.substring(line).trim());
myClasses = pair.first;
myFiles = pair.second;
if (myFiles.length == 0) {
// try find the file with the required name
//todo[nik] it would be better to use FilenameIndex here to honor the scope by it isn't accessible in Open API
@@ -149,25 +146,6 @@ public class ExceptionWorker {
}
}
private PsiClass[] findPositionClasses(String line) {
String className = myInfo.first.substring(line).trim();
PsiClass[] result = findClassesPreferringMyScope(className);
if (result.length == 0) {
final int dollarIndex = className.indexOf('$');
if (dollarIndex >= 0) {
result = findClassesPreferringMyScope(className.substring(0, dollarIndex));
}
}
return result;
}
@NotNull
private PsiClass[] findClassesPreferringMyScope(String className) {
JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(myProject);
PsiClass[] result = psiFacade.findClasses(className, mySearchScope);
return result.length != 0 ? result : psiFacade.findClasses(className, GlobalSearchScope.allScope(myProject));
}
public Filter.Result getResult() {
return myResult;
}
@@ -206,18 +184,18 @@ public class ExceptionWorker {
}
}
final int lparenIdx = line.indexOf('(', startIdx);
if (lparenIdx < 0) return null;
final int dotIdx = line.lastIndexOf('.', lparenIdx);
final int lParenIdx = line.indexOf('(', startIdx);
if (lParenIdx < 0) return null;
final int dotIdx = line.lastIndexOf('.', lParenIdx);
if (dotIdx < 0 || dotIdx < startIdx) return null;
final int rparenIdx = line.indexOf(')', lparenIdx);
if (rparenIdx < 0) return null;
final int rParenIdx = line.indexOf(')', lParenIdx);
if (rParenIdx < 0) return null;
// class, method, link
return Trinity.create(new TextRange(startIdx + 1 + (startIdx >= 0 ? AT.length() : 0), handleSpaces(line, dotIdx, -1, true)),
new TextRange(handleSpaces(line, dotIdx + 1, 1, true), handleSpaces(line, lparenIdx + 1, -1, true)),
new TextRange(lparenIdx, rparenIdx));
new TextRange(handleSpaces(line, dotIdx + 1, 1, true), handleSpaces(line, lParenIdx + 1, -1, true)),
new TextRange(lParenIdx, rParenIdx));
}
private static int handleSpaces(String line, int pos, int delta, boolean skip) {