Commit 2b7769e3 authored by Anna.Kozlova's avatar Anna.Kozlova
Browse files

batch inspections: try to build ref graph on PsiClassOwner

IDEA-175226: unnecessary module dependency for kotlin should work automatically now
parent d20cd4a5
Showing with 67 additions and 2 deletions
+67 -2
...@@ -209,7 +209,9 @@ public abstract class RefJavaElementImpl extends RefElementImpl implements RefJa ...@@ -209,7 +209,9 @@ public abstract class RefJavaElementImpl extends RefElementImpl implements RefJa
callStack.push(this); callStack.push(this);
for (RefElement refCaller : getInReferences()) { for (RefElement refCaller : getInReferences()) {
if (!((RefElementImpl)refCaller).isSuspicious() || !((RefJavaElementImpl)refCaller).isCalledOnlyFrom(refElement, callStack)) { if (!((RefElementImpl)refCaller).isSuspicious() ||
!(refCaller instanceof RefJavaElementImpl) ||
!((RefJavaElementImpl)refCaller).isCalledOnlyFrom(refElement, callStack)) {
callStack.pop(); callStack.pop();
return false; return false;
} }
......
...@@ -39,6 +39,7 @@ import com.intellij.openapi.roots.*; ...@@ -39,6 +39,7 @@ import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService; import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*; import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.javadoc.PsiDocComment;
...@@ -194,9 +195,14 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext ...@@ -194,9 +195,14 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext
final AnalysisScope scope = refManager.getScope(); final AnalysisScope scope = refManager.getScope();
final SearchScope searchScope = new GlobalSearchScope(refManager.getProject()) { final SearchScope searchScope = new GlobalSearchScope(refManager.getProject()) {
private final boolean processedReferences = Registry.is("batch.inspections.process.by.default.jvm.languages");
@Override @Override
public boolean contains(@NotNull VirtualFile file) { public boolean contains(@NotNull VirtualFile file) {
return scope != null && !scope.contains(file) || file.getFileType() != StdFileTypes.JAVA; if (scope != null && !scope.contains(file)) {
return true;
}
return !(processedReferences ? refManager.isInGraph(file) : file.getFileType() == StdFileTypes.JAVA);
} }
@Override @Override
......
...@@ -19,6 +19,7 @@ import com.intellij.analysis.AnalysisScope; ...@@ -19,6 +19,7 @@ import com.intellij.analysis.AnalysisScope;
import com.intellij.openapi.module.Module; import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager; import com.intellij.psi.PsiManager;
import org.jdom.Element; import org.jdom.Element;
...@@ -120,4 +121,12 @@ public abstract class RefManager { ...@@ -120,4 +121,12 @@ public abstract class RefManager {
@NotNull @NotNull
public abstract PsiManager getPsiManager(); public abstract PsiManager getPsiManager();
/**
* @return false if no {@link com.intellij.codeInspection.lang.RefManagerExtension} was registered for language and is not covered by default implementation for PsiClassOwner
* true, otherwise
*/
public boolean isInGraph(VirtualFile file) {
return true;
}
} }
...@@ -44,8 +44,10 @@ import com.intellij.openapi.util.text.StringUtil; ...@@ -44,8 +44,10 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileWithId;
import com.intellij.psi.*; import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightElement; import com.intellij.psi.impl.light.LightElement;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.ConcurrencyUtil; import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.Consumer; import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil;
...@@ -69,6 +71,8 @@ public class RefManagerImpl extends RefManager { ...@@ -69,6 +71,8 @@ public class RefManagerImpl extends RefManager {
private AnalysisScope myScope; private AnalysisScope myScope;
private RefProject myRefProject; private RefProject myRefProject;
private final BitSet myUnprocessedFiles = new BitSet();
private final boolean processJVMClasses = Registry.is("batch.inspections.process.by.default.jvm.languages");
private final ConcurrentMap<PsiAnchor, RefElement> myRefTable = ContainerUtil.newConcurrentMap(); private final ConcurrentMap<PsiAnchor, RefElement> myRefTable = ContainerUtil.newConcurrentMap();
private final ConcurrentMap<PsiElement, RefElement> myPsiToRefTable = ContainerUtil.newConcurrentMap(); // replacement of myRefTable private final ConcurrentMap<PsiElement, RefElement> myPsiToRefTable = ContainerUtil.newConcurrentMap(); // replacement of myRefTable
...@@ -398,6 +402,15 @@ public class RefManagerImpl extends RefManager { ...@@ -398,6 +402,15 @@ public class RefManagerImpl extends RefManager {
return myPsiManager; return myPsiManager;
} }
@Override
public synchronized boolean isInGraph(VirtualFile file) {
return !myUnprocessedFiles.get(((VirtualFileWithId)file).getId());
}
private synchronized void registerUnprocessed(VirtualFileWithId virtualFile) {
myUnprocessedFiles.set(virtualFile.getId());
}
void removeReference(@NotNull RefElement refElem) { void removeReference(@NotNull RefElement refElem) {
final PsiElement element = refElem.getElement(); final PsiElement element = refElem.getElement();
final RefManagerExtension extension = element != null ? getExtension(element.getLanguage()) : null; final RefManagerExtension extension = element != null ? getExtension(element.getLanguage()) : null;
...@@ -452,6 +465,37 @@ public class RefManagerImpl extends RefManager { ...@@ -452,6 +465,37 @@ public class RefManagerImpl extends RefManager {
if (extension != null) { if (extension != null) {
extension.visitElement(element); extension.visitElement(element);
} }
else if (processJVMClasses) {
PsiFile containingFile = element.getContainingFile();
if (containingFile instanceof PsiClassOwner) {
RefElement refFile = getReference(containingFile);
LOG.assertTrue(refFile != null, containingFile);
for (PsiReference reference : element.getReferences()) {
PsiElement resolve = reference.resolve();
if (resolve != null) {
fireNodeMarkedReferenced(resolve, containingFile);
RefElement refWhat = getReference(resolve);
if (refWhat == null) {
PsiFile targetContainingFile = resolve.getContainingFile();
//no logic to distinguish different elements in the file anyway
if (containingFile == targetContainingFile) continue;
refWhat = getReference(targetContainingFile);
}
if (refWhat != null) {
((RefElementImpl)refWhat).addInReference(refFile);
((RefElementImpl)refFile).addOutReference(refWhat);
}
}
}
}
else if (element instanceof PsiFile) {
VirtualFile virtualFile = PsiUtilCore.getVirtualFile(element);
if (virtualFile instanceof VirtualFileWithId) {
registerUnprocessed((VirtualFileWithId)virtualFile);
}
}
}
for (PsiElement aChildren : element.getChildren()) { for (PsiElement aChildren : element.getChildren()) {
aChildren.accept(this); aChildren.accept(this);
} }
......
...@@ -1168,3 +1168,7 @@ dsm.show.cycle.count.in.tooltip=false ...@@ -1168,3 +1168,7 @@ dsm.show.cycle.count.in.tooltip=false
dsm.show.cycle.count.in.tooltip.description=Shows number of cycles found in the tooltip of the Toggle Cycles toolbar button after some calculation time dsm.show.cycle.count.in.tooltip.description=Shows number of cycles found in the tooltip of the Toggle Cycles toolbar button after some calculation time
jdk.regex.soe.workaround=true jdk.regex.soe.workaround=true
jdk.regex.soe.workaround.description=In regular expression pattern replace choice \\n|. with . (and DOT_ALL option) to prevent stack overflow during matching jdk.regex.soe.workaround.description=In regular expression pattern replace choice \\n|. with . (and DOT_ALL option) to prevent stack overflow during matching
batch.inspections.process.by.default.jvm.languages=true
batch.inspections.process.by.default.jvm.languages.description=When building graph for batch inspections, take into account all references inside PsiClassOwner-s. \
This way external references process made shorter and some inspections like Unnecessary module/library dependencies work out of the box for JVM languages.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment