Fixing dependencies: moved the code that walks through project files into the plugin

This commit is contained in:
Andrey Breslav
2011-10-30 12:22:03 +03:00
parent fc01eb2dcf
commit 57bba593ae
15 changed files with 101 additions and 53 deletions
@@ -1,19 +1,12 @@
package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.Sets;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.ex.CompilerPathsEx;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.diagnostics.Errors;
@@ -24,13 +17,21 @@ import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import java.util.Set;
import java.util.Collection;
import java.util.Collections;
/**
* @author abreslav
*/
public class AnalyzerFacade {
public static final Function<JetFile, Collection<JetDeclaration>> SINGLE_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetDeclaration>>() {
@Override
public Collection<JetDeclaration> fun(JetFile file) {
return Collections.<JetDeclaration>singleton(file.getRootNamespace());
}
};
private static final AnalyzingUtils ANALYZING_UTILS = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS);
private final static Key<CachedValue<BindingContext>> BINDING_CONTEXT = Key.create("BINDING_CONTEXT");
private static final Object lock = new Object();
@@ -39,11 +40,13 @@ public class AnalyzerFacade {
return ANALYZING_UTILS.analyzeNamespace(namespace, flowDataTraceFactory);
}
public static BindingContext analyzeFileWithCache(@NotNull final JetFile file) {
return analyzeFileWithCache(ANALYZING_UTILS, file);
public static BindingContext analyzeFileWithCache(@NotNull final JetFile file, @NotNull final Function<JetFile, Collection<JetDeclaration>> declarationProvider) {
return analyzeFileWithCache(ANALYZING_UTILS, file, declarationProvider);
}
public static BindingContext analyzeFileWithCache(@NotNull final AnalyzingUtils analyzingUtils, @NotNull final JetFile file) {
public static BindingContext analyzeFileWithCache(@NotNull final AnalyzingUtils analyzingUtils,
@NotNull final JetFile file,
@NotNull final Function<JetFile, Collection<JetDeclaration>> declarationProvider) {
// TODO : Synchronization?
CachedValue<BindingContext> bindingContextCachedValue = file.getUserData(BINDING_CONTEXT);
if (bindingContextCachedValue == null) {
@@ -51,28 +54,11 @@ public class AnalyzerFacade {
@Override
public Result<BindingContext> compute() {
synchronized (lock) {
final Project project = file.getProject();
final Set<JetDeclaration> namespaces = Sets.newLinkedHashSet();
ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
if (rootManager != null && !ApplicationManager.getApplication().isUnitTestMode()) {
VirtualFile[] contentRoots = rootManager.getContentRoots();
CompilerPathsEx.visitFiles(contentRoots, new CompilerPathsEx.FileVisitor() {
@Override
protected void acceptFile(VirtualFile file, String fileRoot, String filePath) {
if (!(file.getName().endsWith(".kt") || file.getName().endsWith(".kts"))) return;
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
if (psiFile instanceof JetFile) {
namespaces.add(((JetFile) psiFile).getRootNamespace());
}
}
});
}
else {
namespaces.add(file.getRootNamespace());
}
try {
BindingContext bindingContext = analyzingUtils.analyzeNamespaces(project, namespaces, JetControlFlowDataTraceFactory.EMPTY);
BindingContext bindingContext = analyzingUtils.analyzeNamespaces(
file.getProject(),
declarationProvider.fun(file),
JetControlFlowDataTraceFactory.EMPTY);
return new Result<BindingContext>(bindingContext, PsiModificationTracker.MODIFICATION_COUNT);
}
catch (ProcessCanceledException e) {
@@ -86,6 +72,7 @@ public class AnalyzerFacade {
}
}
}
}, false);
file.putUserData(BINDING_CONTEXT, bindingContextCachedValue);
}
@@ -81,7 +81,7 @@ public class CheckerTestUtilTest extends JetLiteFixture {
}
public void test(PsiFile psiFile) {
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(AnalyzingUtils.getInstance(ImportingStrategy.NONE), (JetFile) psiFile);
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(AnalyzingUtils.getInstance(ImportingStrategy.NONE), (JetFile) psiFile, AnalyzerFacade.SINGLE_DECLARATION_PROVIDER);
String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, bindingContext).toString();
List<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList();
@@ -42,7 +42,7 @@ public class FullJetPsiCheckerTest extends JetLiteFixture {
String clearText = CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
myFile = createPsiFile(myName, clearText);
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(myFile);
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(myFile, AnalyzerFacade.SINGLE_DECLARATION_PROVIDER);
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, bindingContext.getDiagnostics(), new CheckerTestUtil.DiagnosticDiffCallbacks() {
@Override
@@ -40,7 +40,7 @@ public class QuickJetPsiCheckerTest extends JetLiteFixture {
createAndCheckPsiFile(name, clearText);
JetFile jetFile = (JetFile) myFile;
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(AnalyzingUtils.getInstance(ImportingStrategy.NONE), jetFile);
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(AnalyzingUtils.getInstance(ImportingStrategy.NONE), jetFile, AnalyzerFacade.SINGLE_DECLARATION_PROVIDER);
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, bindingContext.getDiagnostics(), new CheckerTestUtil.DiagnosticDiffCallbacks() {
@Override
@@ -44,7 +44,7 @@ public class JetDefaultModalityModifiersTest extends JetLiteFixture {
List<JetDeclaration> declarations = file.getRootNamespace().getDeclarations();
JetDeclaration aClass = declarations.get(0);
assert aClass instanceof JetClass;
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file, AnalyzerFacade.SINGLE_DECLARATION_PROVIDER);
DeclarationDescriptor classDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, aClass);
WritableScopeImpl scope = new WritableScopeImpl(libraryScope, root, RedeclarationHandler.DO_NOTHING);
assert classDescriptor instanceof ClassifierDescriptor;
@@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import org.jetbrains.jet.resolve.DescriptorRenderer;
/**
@@ -26,7 +27,7 @@ public class JetQuickDocumentationProvider extends AbstractDocumentationProvider
ref = PsiTreeUtil.getParentOfType(originalElement, JetReferenceExpression.class);
}
if (ref != null) {
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache((JetFile) element.getContainingFile());
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) element.getContainingFile());
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, ref);
if (declarationDescriptor != null) {
return render(declarationDescriptor);
@@ -11,6 +11,7 @@ import org.jetbrains.jet.checkers.CheckerTestUtil;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
@@ -28,7 +29,7 @@ public class CopyAsDiagnosticTestAction extends AnAction {
PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE);
assert editor != null && psiFile != null;
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache((JetFile) psiFile);
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) psiFile);
String result = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, bindingContext).toString();
@@ -12,9 +12,9 @@ import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.plugin.JetLanguage;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
/**
* @author yole
@@ -26,7 +26,7 @@ public class ShowExpressionTypeAction extends AnAction {
PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE);
assert editor != null && psiFile != null;
JetExpression expression;
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache((JetFile) psiFile);
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) psiFile);
if (editor.getSelectionModel().hasSelection()) {
int startOffset = editor.getSelectionModel().getSelectionStart();
int endOffset = editor.getSelectionModel().getSelectionEnd();
@@ -20,6 +20,7 @@ import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.JetHighlighter;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import java.util.Collection;
import java.util.Set;
@@ -53,7 +54,7 @@ public class DebugInfoAnnotator implements Annotator {
if (element instanceof JetFile) {
JetFile file = (JetFile) element;
try {
final BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
final Set<JetReferenceExpression> unresolvedReferences = Sets.newHashSet();
for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
@@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import javax.swing.*;
@@ -45,7 +45,7 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
JetFile file = PsiTreeUtil.getParentOfType(element, JetFile.class);
if (file == null) return null;
final BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
if (element instanceof JetClass) {
JetClass jetClass = (JetClass) element;
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.plugin.JetHighlighter;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import org.jetbrains.jet.plugin.quickfix.JetIntentionActionFactory;
import org.jetbrains.jet.plugin.quickfix.QuickFixes;
@@ -54,7 +55,7 @@ public class JetPsiChecker implements Annotator {
JetFile file = (JetFile) element;
Project project = element.getProject();
try {
final BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
if (errorReportingEnabled) {
Collection<Diagnostic> diagnostics = Sets.newLinkedHashSet(bindingContext.getDiagnostics());
@@ -0,0 +1,57 @@
package org.jetbrains.jet.plugin.compiler;
import com.google.common.collect.Sets;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.ex.CompilerPathsEx;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import java.util.Collection;
import java.util.Set;
/**
* @author abreslav
*/
public class WholeProjectAnalyzerFacade {
public static final Function<JetFile, Collection<JetDeclaration>> WHOLE_PROJECT_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetDeclaration>>() {
@Override
public Collection<JetDeclaration> fun(JetFile file) {
final Project project = file.getProject();
final Set<JetDeclaration> namespaces = Sets.newLinkedHashSet();
ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
if (rootManager != null && !ApplicationManager.getApplication().isUnitTestMode()) {
VirtualFile[] contentRoots = rootManager.getContentRoots();
CompilerPathsEx.visitFiles(contentRoots, new CompilerPathsEx.FileVisitor() {
@Override
protected void acceptFile(VirtualFile file, String fileRoot, String filePath) {
if (!(file.getName().endsWith(".kt") || file.getName().endsWith(".kts"))) return;
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
if (psiFile instanceof JetFile) {
namespaces.add(((JetFile) psiFile).getRootNamespace());
}
}
});
}
else {
namespaces.add(file.getRootNamespace());
}
return namespaces;
}
};
@NotNull
public static BindingContext analyzeProjectWithCacheOnAFile(@NotNull JetFile file) {
return AnalyzerFacade.analyzeFileWithCache(file, WHOLE_PROJECT_DECLARATION_PROVIDER);
}
}
@@ -21,8 +21,8 @@ import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import java.util.*;
@@ -125,7 +125,7 @@ public class JetPositionManager implements PositionManager {
if (mapper != null) {
return mapper;
}
final BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(myDebugProcess.getProject());
final JetTypeMapper typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
file.acceptChildren(new JetVisitorVoid() {
@@ -12,7 +12,7 @@ import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import java.util.Collection;
@@ -76,7 +76,7 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
protected PsiElement doResolve() {
JetFile file = (JetFile) getElement().getContainingFile();
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
PsiElement psiElement = BindingContextUtils.resolveToDeclarationPsiElement(bindingContext, myExpression);
if (psiElement != null) {
return psiElement;
@@ -88,7 +88,7 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
protected ResolveResult[] doMultiResolve() {
JetFile file = (JetFile) getElement().getContainingFile();
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
Collection<? extends ResolvedCallImpl<? extends DeclarationDescriptor>> resolvedCalls = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
if (resolvedCalls == null) return ResolveResult.EMPTY_ARRAY;
ResolveResult[] results = new ResolveResult[resolvedCalls.size()];
@@ -13,9 +13,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import java.util.List;
@@ -51,7 +51,7 @@ class JetSimpleNameReference extends JetPsiReference {
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) parent;
JetExpression receiverExpression = qualifiedExpression.getReceiverExpression();
JetFile file = (JetFile) myExpression.getContainingFile();
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
final JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, receiverExpression);
if (expressionType != null) {
return collectLookupElements(bindingContext, expressionType.getMemberScope());
@@ -59,7 +59,7 @@ class JetSimpleNameReference extends JetPsiReference {
}
else {
JetFile file = (JetFile) myExpression.getContainingFile();
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
JetScope resolutionScope = bindingContext.get(BindingContext.RESOLUTION_SCOPE, myExpression);
if (resolutionScope != null) {
return collectLookupElements(bindingContext, resolutionScope);