Use lazy resolve in completion
This commit is contained in:
@@ -51,12 +51,15 @@ public final class TipsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Collection<DeclarationDescriptor> getReferenceVariants(JetSimpleNameExpression expression, BindingContext context) {
|
public static Collection<DeclarationDescriptor> getReferenceVariants(
|
||||||
|
@NotNull final JetSimpleNameExpression expression,
|
||||||
|
@NotNull final BindingContext context
|
||||||
|
) {
|
||||||
JetExpression receiverExpression = expression.getReceiverExpression();
|
JetExpression receiverExpression = expression.getReceiverExpression();
|
||||||
if (receiverExpression != null) {
|
if (receiverExpression != null) {
|
||||||
// Process as call expression
|
// Process as call expression
|
||||||
final JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
|
JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
|
||||||
final JetType expressionType = context.get(BindingContext.EXPRESSION_TYPE, receiverExpression);
|
JetType expressionType = context.get(BindingContext.EXPRESSION_TYPE, receiverExpression);
|
||||||
|
|
||||||
if (expressionType != null && resolutionScope != null) {
|
if (expressionType != null && resolutionScope != null) {
|
||||||
if (!(expressionType instanceof NamespaceType)) {
|
if (!(expressionType instanceof NamespaceType)) {
|
||||||
@@ -116,7 +119,7 @@ public final class TipsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Collection<DeclarationDescriptor> getReferenceVariants(JetNamespaceHeader expression, BindingContext context) {
|
public static Collection<DeclarationDescriptor> getPackageReferenceVariants(JetSimpleNameExpression expression, BindingContext context) {
|
||||||
JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
|
JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
|
||||||
if (resolutionScope != null) {
|
if (resolutionScope != null) {
|
||||||
return excludeNonPackageDescriptors(resolutionScope.getAllDescriptors());
|
return excludeNonPackageDescriptors(resolutionScope.getAllDescriptors());
|
||||||
|
|||||||
+201
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2012 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 org.jetbrains.jet.lang.resolve.lazy;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.intellij.openapi.diagnostic.Logger;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.PsiFile;
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.di.InjectorForBodyResolve;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
|
import org.jetbrains.jet.lang.resolve.*;
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nikolay Krasko
|
||||||
|
*/
|
||||||
|
public class LazyBindingContextUtils {
|
||||||
|
private static final Logger LOG = Logger.getInstance("#" + LazyBindingContextUtils.class.getName());
|
||||||
|
|
||||||
|
private LazyBindingContextUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class EmptyBodyResolveContext implements BodiesResolveContext {
|
||||||
|
@Override
|
||||||
|
public Map<JetClass, MutableClassDescriptor> getClasses() {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<JetObjectDeclaration, MutableClassDescriptor> getObjects() {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<JetProperty, PropertyDescriptor> getProperties() {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<JetNamedFunction, SimpleFunctionDescriptor> getFunctions() {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<JetDeclaration, JetScope> getDeclaringScopes() {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<JetScript, ScriptDescriptor> getScripts() {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<JetScript, WritableScope> getScriptScopes() {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTopDownAnalysisParameters(TopDownAnalysisParameters parameters) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean completeAnalysisNeeded(@NotNull PsiElement element) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @NotNull BindingContext getExpressionBindingContext(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) {
|
||||||
|
final DelegatingBindingTrace trace = new DelegatingBindingTrace(resolveSession.getBindingContext());
|
||||||
|
|
||||||
|
JetFile file = (JetFile) expression.getContainingFile();
|
||||||
|
|
||||||
|
// Resolve enclosing function body
|
||||||
|
JetNamedFunction namedFunction = PsiTreeUtil.getTopmostParentOfType(expression, JetNamedFunction.class);
|
||||||
|
if (namedFunction != null) {
|
||||||
|
TopDownAnalysisParameters parameters = new TopDownAnalysisParameters(
|
||||||
|
Predicates.<PsiFile>alwaysTrue(), false, true, Collections.<AnalyzerScriptParameter>emptyList());
|
||||||
|
|
||||||
|
InjectorForBodyResolve bodyResolve = new InjectorForBodyResolve(file.getProject(), parameters, trace, new EmptyBodyResolveContext());
|
||||||
|
|
||||||
|
final BodyResolver bodyResolver = bodyResolve.getBodyResolver();
|
||||||
|
|
||||||
|
if (namedFunction.getParent() instanceof JetFile ||
|
||||||
|
namedFunction.getParent() instanceof JetClassBody ||
|
||||||
|
namedFunction.getParent() instanceof JetClassObject) {
|
||||||
|
JetScope scope = resolveSession.getResolutionScope(namedFunction);
|
||||||
|
FunctionDescriptor functionDescriptor = (FunctionDescriptor) resolveSession.resolveToDescriptor(namedFunction);
|
||||||
|
bodyResolver.resolveFunctionBody(trace, namedFunction, functionDescriptor, scope);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG.warn(String.format("Not expected parent for function: %s in %s",
|
||||||
|
namedFunction.getName(), namedFunction.getContainingFile()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trace.getBindingContext().get(BindingContext.RESOLUTION_SCOPE, expression) == null) {
|
||||||
|
JetScope scope = getExpressionMemberScope(resolveSession, expression);
|
||||||
|
if (scope != null) {
|
||||||
|
trace.record(BindingContext.RESOLUTION_SCOPE, expression, scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return trace.getBindingContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JetScope getExpressionOuterScope(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) {
|
||||||
|
JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class);
|
||||||
|
// DeclarationDescriptor descriptor = resolveToDescriptor(parentDeclaration);
|
||||||
|
return resolveSession.getResolutionScope(parentDeclaration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JetScope getExpressionMemberScope(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) {
|
||||||
|
DelegatingBindingTrace trace = new DelegatingBindingTrace(resolveSession.getBindingContext());
|
||||||
|
|
||||||
|
if (expression instanceof JetReferenceExpression) {
|
||||||
|
// In some type declaration
|
||||||
|
if (expression.getParent() instanceof JetUserType) {
|
||||||
|
JetUserType qualifier = ((JetUserType) expression.getParent()).getQualifier();
|
||||||
|
if (qualifier != null) {
|
||||||
|
Collection<? extends DeclarationDescriptor> descriptors = resolveSession.getInjector().getQualifiedExpressionResolver()
|
||||||
|
.lookupDescriptorsForUserType(qualifier, getExpressionOuterScope(resolveSession, expression), trace);
|
||||||
|
|
||||||
|
for (DeclarationDescriptor descriptor : descriptors) {
|
||||||
|
if (descriptor instanceof LazyPackageDescriptor) {
|
||||||
|
return ((LazyPackageDescriptor) descriptor).getMemberScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inside import
|
||||||
|
if (PsiTreeUtil.getParentOfType(expression, JetImportDirective.class, false) != null) {
|
||||||
|
if (expression.getParent() instanceof JetDotQualifiedExpression) {
|
||||||
|
JetExpression element = ((JetDotQualifiedExpression) expression.getParent()).getReceiverExpression();
|
||||||
|
|
||||||
|
NamespaceDescriptor filePackage = resolveSession.getPackageDescriptorByFqName(
|
||||||
|
new FqName(((JetFile) expression.getContainingFile()).getPackageName()));
|
||||||
|
|
||||||
|
NamespaceDescriptor rootPackage = resolveSession.getPackageDescriptorByFqName(FqName.ROOT);
|
||||||
|
|
||||||
|
Collection<? extends DeclarationDescriptor> descriptors;
|
||||||
|
|
||||||
|
if (element instanceof JetDotQualifiedExpression) {
|
||||||
|
descriptors = resolveSession.getInjector().getQualifiedExpressionResolver().lookupDescriptorsForQualifiedExpression(
|
||||||
|
(JetDotQualifiedExpression) element, rootPackage.getMemberScope(), filePackage.getMemberScope(), trace, false, false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
descriptors = resolveSession.getInjector().getQualifiedExpressionResolver().lookupDescriptorsForSimpleNameReference(
|
||||||
|
(JetSimpleNameExpression) element, rootPackage.getMemberScope(), filePackage.getMemberScope(), trace, false, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DeclarationDescriptor descriptor : descriptors) {
|
||||||
|
if (descriptor instanceof NamespaceDescriptor) {
|
||||||
|
return ((NamespaceDescriptor) descriptor).getMemberScope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return resolveSession.getPackageDescriptorByFqName(FqName.ROOT).getMemberScope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inside package declaration
|
||||||
|
JetNamespaceHeader namespaceHeader = PsiTreeUtil.getParentOfType(expression, JetNamespaceHeader.class, false);
|
||||||
|
if (namespaceHeader != null) {
|
||||||
|
NamespaceDescriptor packageDescriptor = resolveSession.getPackageDescriptorByFqName(
|
||||||
|
namespaceHeader.getParentFqName((JetReferenceExpression)expression));
|
||||||
|
if (packageDescriptor != null) {
|
||||||
|
return packageDescriptor.getMemberScope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ package org.jetbrains.jet.plugin.caches;
|
|||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.Collections2;
|
import com.google.common.collect.Collections2;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.util.Condition;
|
import com.intellij.openapi.util.Condition;
|
||||||
import com.intellij.psi.PsiClass;
|
import com.intellij.psi.PsiClass;
|
||||||
@@ -39,6 +40,8 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
|
|||||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||||
import org.jetbrains.jet.lang.resolve.ImportPath;
|
import org.jetbrains.jet.lang.resolve.ImportPath;
|
||||||
import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
|
import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
|
||||||
|
import org.jetbrains.jet.lang.resolve.lazy.LazyBindingContextUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
|
||||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
@@ -155,22 +158,25 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
|||||||
@NotNull JetSimpleNameExpression expression,
|
@NotNull JetSimpleNameExpression expression,
|
||||||
@NotNull GlobalSearchScope scope
|
@NotNull GlobalSearchScope scope
|
||||||
) {
|
) {
|
||||||
HashSet<FunctionDescriptor> result = new HashSet<FunctionDescriptor>();
|
|
||||||
|
|
||||||
JetFile jetFile = (JetFile) expression.getContainingFile();
|
JetFile jetFile = (JetFile) expression.getContainingFile();
|
||||||
BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(jetFile).getBindingContext();
|
final ResolveSession resolveSessionForFile = WholeProjectAnalyzerFacade.getLazyResolveSessionForFile(jetFile);
|
||||||
|
LazyBindingContextUtils.getExpressionBindingContext(resolveSessionForFile, expression);
|
||||||
|
BindingContext context = WholeProjectAnalyzerFacade.getLazyResolveContext(jetFile, expression);
|
||||||
JetScope jetScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
|
JetScope jetScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
|
||||||
|
|
||||||
if (jetScope == null) {
|
if (jetScope == null) {
|
||||||
return result;
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Set<FunctionDescriptor> result = Sets.newHashSet();
|
||||||
|
|
||||||
Collection<PsiMethod> topLevelFunctionPrototypes = JetFromJavaDescriptorHelper.getTopLevelFunctionPrototypesByName(name, project, scope);
|
Collection<PsiMethod> topLevelFunctionPrototypes = JetFromJavaDescriptorHelper.getTopLevelFunctionPrototypesByName(name, project, scope);
|
||||||
for (PsiMethod method : topLevelFunctionPrototypes) {
|
for (PsiMethod method : topLevelFunctionPrototypes) {
|
||||||
FqName functionFQN = JetFromJavaDescriptorHelper.getJetTopLevelDeclarationFQN(method);
|
FqName functionFQN = JetFromJavaDescriptorHelper.getJetTopLevelDeclarationFQN(method);
|
||||||
if (functionFQN != null) {
|
if (functionFQN != null) {
|
||||||
JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, new ImportPath(functionFQN, false));
|
JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, new ImportPath(functionFQN, false));
|
||||||
Collection<? extends DeclarationDescriptor> declarationDescriptors = new QualifiedExpressionResolver().analyseImportReference(importDirective, jetScope, new BindingTraceContext());
|
Collection<? extends DeclarationDescriptor> declarationDescriptors = new QualifiedExpressionResolver().analyseImportReference(
|
||||||
|
importDirective, jetScope, new BindingTraceContext());
|
||||||
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
|
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
|
||||||
if (declarationDescriptor instanceof FunctionDescriptor) {
|
if (declarationDescriptor instanceof FunctionDescriptor) {
|
||||||
result.add((FunctionDescriptor) declarationDescriptor);
|
result.add((FunctionDescriptor) declarationDescriptor);
|
||||||
@@ -181,10 +187,8 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
|||||||
|
|
||||||
Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope);
|
Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope);
|
||||||
for (JetNamedFunction jetNamedFunction : jetNamedFunctions) {
|
for (JetNamedFunction jetNamedFunction : jetNamedFunctions) {
|
||||||
SimpleFunctionDescriptor functionDescriptor = context.get(BindingContext.FUNCTION, jetNamedFunction);
|
FunctionDescriptor functionDescriptor = (FunctionDescriptor) resolveSessionForFile.resolveToDescriptor(jetNamedFunction);
|
||||||
if (functionDescriptor != null) {
|
result.add(functionDescriptor);
|
||||||
result.add(functionDescriptor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -224,7 +228,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
|||||||
|
|
||||||
JetFile jetFile = (JetFile) expression.getContainingFile();
|
JetFile jetFile = (JetFile) expression.getContainingFile();
|
||||||
|
|
||||||
BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(jetFile).getBindingContext();
|
BindingContext context = WholeProjectAnalyzerFacade.getLazyResolveContext(jetFile, expression);
|
||||||
JetExpression receiverExpression = expression.getReceiverExpression();
|
JetExpression receiverExpression = expression.getReceiverExpression();
|
||||||
|
|
||||||
if (receiverExpression != null) {
|
if (receiverExpression != null) {
|
||||||
@@ -273,7 +277,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
|||||||
@NotNull Condition<String> acceptedShortNameCondition,
|
@NotNull Condition<String> acceptedShortNameCondition,
|
||||||
@NotNull JetFile jetFile
|
@NotNull JetFile jetFile
|
||||||
) {
|
) {
|
||||||
BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(jetFile).getBindingContext();
|
BindingContext context = WholeProjectAnalyzerFacade.getLazyResolveContext(jetFile, null);
|
||||||
Collection<ClassDescriptor> classDescriptors = new ArrayList<ClassDescriptor>();
|
Collection<ClassDescriptor> classDescriptors = new ArrayList<ClassDescriptor>();
|
||||||
|
|
||||||
for (String fqName : JetFullClassNameIndex.getInstance().getAllKeys(project)) {
|
for (String fqName : JetFullClassNameIndex.getInstance().getAllKeys(project)) {
|
||||||
|
|||||||
@@ -21,18 +21,23 @@ import com.intellij.codeInsight.lookup.LookupElement;
|
|||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.util.Condition;
|
import com.intellij.openapi.util.Condition;
|
||||||
import com.intellij.psi.PsiClass;
|
import com.intellij.psi.PsiClass;
|
||||||
|
import com.intellij.psi.PsiFile;
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
import com.intellij.util.Consumer;
|
import com.intellij.util.Consumer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.asJava.JetLightClass;
|
import org.jetbrains.jet.asJava.JetLightClass;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
|
||||||
import org.jetbrains.jet.plugin.caches.JetCacheManager;
|
import org.jetbrains.jet.plugin.caches.JetCacheManager;
|
||||||
import org.jetbrains.jet.plugin.caches.JetShortNamesCache;
|
import org.jetbrains.jet.plugin.caches.JetShortNamesCache;
|
||||||
import org.jetbrains.jet.plugin.completion.handlers.JetJavaClassInsertHandler;
|
import org.jetbrains.jet.plugin.completion.handlers.JetJavaClassInsertHandler;
|
||||||
import org.jetbrains.jet.plugin.project.JsModuleDetector;
|
import org.jetbrains.jet.plugin.project.JsModuleDetector;
|
||||||
import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade;
|
import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade;
|
||||||
|
import org.jetbrains.jet.plugin.stubindex.JetFullClassNameIndex;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
@@ -40,34 +45,7 @@ import java.util.Collection;
|
|||||||
* @author Nikolay Krasko
|
* @author Nikolay Krasko
|
||||||
*/
|
*/
|
||||||
public class JetClassCompletionContributor extends CompletionContributor {
|
public class JetClassCompletionContributor extends CompletionContributor {
|
||||||
public JetClassCompletionContributor() {
|
public JetClassCompletionContributor() {}
|
||||||
// Should be removed in new idea
|
|
||||||
//extend(CompletionType.CLASS_NAME, PlatformPatterns.psiElement(),
|
|
||||||
// new CompletionProvider<CompletionParameters>() {
|
|
||||||
// @Override
|
|
||||||
// protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context,
|
|
||||||
// final @NotNull CompletionResultSet result) {
|
|
||||||
// final CompletionResultSet jetResult = JetCompletionSorting.addJetSorting(parameters, result);
|
|
||||||
//
|
|
||||||
// final PsiElement position = parameters.getPosition();
|
|
||||||
// if (!(position.getContainingFile() instanceof JetFile)) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// final PsiReference ref = position.getContainingFile().findReferenceAt(parameters.getOffset());
|
|
||||||
// if (ref instanceof JetSimpleNameReference) {
|
|
||||||
// addClasses(parameters, result, new Consumer<LookupElement>() {
|
|
||||||
// @Override
|
|
||||||
// public void consume(LookupElement lookupElement) {
|
|
||||||
// jetResult.addElement(lookupElement);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// result.stopHere();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Jet classes will be added as java completions for unification
|
* Jet classes will be added as java completions for unification
|
||||||
@@ -75,17 +53,14 @@ public class JetClassCompletionContributor extends CompletionContributor {
|
|||||||
static void addClasses(
|
static void addClasses(
|
||||||
@NotNull final CompletionParameters parameters,
|
@NotNull final CompletionParameters parameters,
|
||||||
@NotNull final CompletionResultSet result,
|
@NotNull final CompletionResultSet result,
|
||||||
|
@NotNull final BindingContext jetContext,
|
||||||
@NotNull final Consumer<LookupElement> consumer
|
@NotNull final Consumer<LookupElement> consumer
|
||||||
) {
|
) {
|
||||||
CompletionResultSet tempResult = result.withPrefixMatcher(CompletionUtil.findReferenceOrAlphanumericPrefix(parameters));
|
CompletionResultSet tempResult = result.withPrefixMatcher(CompletionUtil.findReferenceOrAlphanumericPrefix(parameters));
|
||||||
|
|
||||||
// TODO: Make icon for standard types
|
|
||||||
final Collection<DeclarationDescriptor> jetOnlyClasses = JetShortNamesCache.getJetOnlyTypes();
|
final Collection<DeclarationDescriptor> jetOnlyClasses = JetShortNamesCache.getJetOnlyTypes();
|
||||||
final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(
|
|
||||||
(JetFile)parameters.getPosition().getContainingFile()).getBindingContext();
|
|
||||||
|
|
||||||
for (DeclarationDescriptor jetOnlyClass : jetOnlyClasses) {
|
for (DeclarationDescriptor jetOnlyClass : jetOnlyClasses) {
|
||||||
consumer.consume(DescriptorLookupConverter.createLookupElement(bindingContext, jetOnlyClass));
|
consumer.consume(DescriptorLookupConverter.createLookupElement(jetContext, jetOnlyClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!JsModuleDetector.isJsModule((JetFile)parameters.getOriginalFile())) {
|
if (!JsModuleDetector.isJsModule((JetFile)parameters.getOriginalFile())) {
|
||||||
@@ -99,8 +74,8 @@ public class JetClassCompletionContributor extends CompletionContributor {
|
|||||||
if (lookupElement instanceof JavaPsiClassReferenceElement) {
|
if (lookupElement instanceof JavaPsiClassReferenceElement) {
|
||||||
JavaPsiClassReferenceElement javaPsiReferenceElement = (JavaPsiClassReferenceElement) lookupElement;
|
JavaPsiClassReferenceElement javaPsiReferenceElement = (JavaPsiClassReferenceElement) lookupElement;
|
||||||
|
|
||||||
PsiClass object = javaPsiReferenceElement.getObject();
|
PsiClass psiClass = javaPsiReferenceElement.getObject();
|
||||||
if (addAsJetLookupElement(object, bindingContext, consumer)) {
|
if (addAsJetLookupElement(parameters, psiClass, consumer)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,20 +99,30 @@ public class JetClassCompletionContributor extends CompletionContributor {
|
|||||||
(JetFile) parameters.getOriginalFile());
|
(JetFile) parameters.getOriginalFile());
|
||||||
|
|
||||||
for (ClassDescriptor descriptor : descriptors) {
|
for (ClassDescriptor descriptor : descriptors) {
|
||||||
consumer.consume(DescriptorLookupConverter.createLookupElement(bindingContext, descriptor));
|
consumer.consume(DescriptorLookupConverter.createLookupElement(jetContext, descriptor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean addAsJetLookupElement(PsiClass aClass, BindingContext bindingContext, Consumer<LookupElement> consumer) {
|
private static boolean addAsJetLookupElement(CompletionParameters parameters, PsiClass aClass, Consumer<LookupElement> consumer) {
|
||||||
if (aClass instanceof JetLightClass) {
|
if (aClass instanceof JetLightClass) {
|
||||||
ClassDescriptor descriptor = bindingContext.get(
|
Project project = parameters.getPosition().getProject();
|
||||||
BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, ((JetLightClass)aClass).getFqName());
|
PsiFile completionFile = parameters.getPosition().getContainingFile();
|
||||||
|
|
||||||
if (descriptor != null) {
|
Collection<JetClassOrObject> classOrObjects =
|
||||||
LookupElement element = DescriptorLookupConverter.createLookupElement(bindingContext, descriptor);
|
JetFullClassNameIndex.getInstance().get(aClass.getQualifiedName(), project, GlobalSearchScope.allScope(project));
|
||||||
consumer.consume(element);
|
|
||||||
return true;
|
for (JetClassOrObject classOrObject : classOrObjects) {
|
||||||
|
if (classOrObject.getContainingFile().getOriginalFile().equals(aClass.getContainingFile())) {
|
||||||
|
PsiFile fileOfClass = completionFile.getOriginalFile().equals(aClass.getContainingFile()) ? completionFile : aClass.getContainingFile();
|
||||||
|
|
||||||
|
ResolveSession resolveSessionForFile = WholeProjectAnalyzerFacade.getLazyResolveSessionForFile((JetFile) fileOfClass);
|
||||||
|
ClassDescriptor descriptor = resolveSessionForFile.getClassDescriptor(classOrObject);
|
||||||
|
|
||||||
|
LookupElement element = DescriptorLookupConverter.createLookupElement(resolveSessionForFile.getBindingContext(), descriptor);
|
||||||
|
consumer.consume(element);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,20 +77,18 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
|
|
||||||
JetSimpleNameReference jetReference = getJetReference(parameters);
|
JetSimpleNameReference jetReference = getJetReference(parameters);
|
||||||
if (jetReference != null) {
|
if (jetReference != null) {
|
||||||
|
BindingContext jetContext = WholeProjectAnalyzerFacade.getLazyResolveContext(
|
||||||
BindingContext jetContext =
|
(JetFile) position.getContainingFile(), jetReference.getExpression());
|
||||||
WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile)position.getContainingFile())
|
|
||||||
.getBindingContext();
|
|
||||||
|
|
||||||
JetScope scope = jetContext.get(BindingContext.RESOLUTION_SCOPE, jetReference.getExpression());
|
JetScope scope = jetContext.get(BindingContext.RESOLUTION_SCOPE, jetReference.getExpression());
|
||||||
session.inDescriptor = scope != null ? scope.getContainingDeclaration() : null;
|
session.inDescriptor = scope != null ? scope.getContainingDeclaration() : null;
|
||||||
|
|
||||||
completeForReference(parameters, result, position, jetReference, session);
|
completeForReference(parameters, result, position, jetReference, session, jetContext);
|
||||||
|
|
||||||
if (!session.isSomethingAdded && session.customInvocationCount == 0) {
|
if (!session.isSomethingAdded && session.customInvocationCount == 0) {
|
||||||
// Rerun completion if nothing was found
|
// Rerun completion if nothing was found
|
||||||
session.customInvocationCount = 1;
|
session.customInvocationCount = 1;
|
||||||
completeForReference(parameters, result, position, jetReference, session);
|
completeForReference(parameters, result, position, jetReference, session, jetContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,18 +103,18 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
@NotNull CompletionResultSet result,
|
@NotNull CompletionResultSet result,
|
||||||
@NotNull PsiElement position,
|
@NotNull PsiElement position,
|
||||||
@NotNull JetSimpleNameReference jetReference,
|
@NotNull JetSimpleNameReference jetReference,
|
||||||
@NotNull CompletionSession session
|
@NotNull CompletionSession session,
|
||||||
) {
|
BindingContext jetContext) {
|
||||||
if (isOnlyKeywordCompletion(position)) {
|
if (isOnlyKeywordCompletion(position)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldRunTypeCompletionOnly(position, jetReference)) {
|
if (shouldRunTypeCompletionOnly(position, jetReference)) {
|
||||||
if (session.customInvocationCount > 0) {
|
if (session.customInvocationCount > 0) {
|
||||||
addClasses(parameters, result, session);
|
addClasses(parameters, result, session, jetContext);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (LookupElement variant : getReferenceVariants(jetReference, result, session)) {
|
for (LookupElement variant : getReferenceVariants(jetReference, result, session, jetContext)) {
|
||||||
if (isTypeDeclaration(variant)) {
|
if (isTypeDeclaration(variant)) {
|
||||||
addCheckedCompletionToResult(result, variant, session);
|
addCheckedCompletionToResult(result, variant, session);
|
||||||
}
|
}
|
||||||
@@ -126,7 +124,7 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (LookupElement variant : getReferenceVariants(jetReference, result, session)) {
|
for (LookupElement variant : getReferenceVariants(jetReference, result, session, jetContext)) {
|
||||||
addCheckedCompletionToResult(result, variant, session);
|
addCheckedCompletionToResult(result, variant, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +142,7 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (shouldRunTopLevelCompletion(parameters, session)) {
|
if (shouldRunTopLevelCompletion(parameters, session)) {
|
||||||
addClasses(parameters, result, session);
|
addClasses(parameters, result, session, jetContext);
|
||||||
addJetTopLevelFunctions(jetReference.getExpression(), result, position, session);
|
addJetTopLevelFunctions(jetReference.getExpression(), result, position, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,12 +155,12 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
return PsiTreeUtil.getParentOfType(position, JetModifierList.class) != null;
|
return PsiTreeUtil.getParentOfType(position, JetModifierList.class) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addJetExtensions(JetSimpleNameExpression expression, CompletionResultSet result, PsiElement position) {
|
private static void addJetExtensions(@NotNull JetSimpleNameExpression expression, @NotNull CompletionResultSet result, @NotNull PsiElement position) {
|
||||||
final PrefixMatcher prefixMatcher = result.getPrefixMatcher();
|
final PrefixMatcher prefixMatcher = result.getPrefixMatcher();
|
||||||
JetShortNamesCache namesCache = JetCacheManager.getInstance(position.getProject()).getNamesCache();
|
JetShortNamesCache namesCache = JetCacheManager.getInstance(position.getProject()).getNamesCache();
|
||||||
Condition<String> matchPrefixCondition = new Condition<String>() {
|
Condition<String> matchPrefixCondition = new Condition<String>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean value(String callableName) {
|
public boolean value(@NotNull String callableName) {
|
||||||
return prefixMatcher.prefixMatches(callableName);
|
return prefixMatcher.prefixMatches(callableName);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -170,8 +168,8 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
Collection<DeclarationDescriptor> jetCallableExtensions = namesCache.getJetCallableExtensions(
|
Collection<DeclarationDescriptor> jetCallableExtensions = namesCache.getJetCallableExtensions(
|
||||||
matchPrefixCondition, expression, GlobalSearchScope.allScope(position.getProject()));
|
matchPrefixCondition, expression, GlobalSearchScope.allScope(position.getProject()));
|
||||||
|
|
||||||
BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile)position.getContainingFile())
|
BindingContext context = WholeProjectAnalyzerFacade.getLazyResolveContext(
|
||||||
.getBindingContext();
|
(JetFile) position.getContainingFile(), expression);
|
||||||
|
|
||||||
for (DeclarationDescriptor jetCallableExtension : jetCallableExtensions) {
|
for (DeclarationDescriptor jetCallableExtension : jetCallableExtensions) {
|
||||||
result.addElement(DescriptorLookupConverter.createLookupElement(context, jetCallableExtension));
|
result.addElement(DescriptorLookupConverter.createLookupElement(context, jetCallableExtension));
|
||||||
@@ -192,11 +190,10 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addJetTopLevelFunctions(JetSimpleNameExpression expression,
|
private static void addJetTopLevelFunctions(@NotNull JetSimpleNameExpression expression,
|
||||||
@NotNull CompletionResultSet result,
|
@NotNull CompletionResultSet result,
|
||||||
@NotNull PsiElement position,
|
@NotNull PsiElement position,
|
||||||
@NotNull CompletionSession session) {
|
@NotNull CompletionSession session) {
|
||||||
|
|
||||||
String actualPrefix = result.getPrefixMatcher().getPrefix();
|
String actualPrefix = result.getPrefixMatcher().getPrefix();
|
||||||
|
|
||||||
Project project = position.getProject();
|
Project project = position.getProject();
|
||||||
@@ -205,8 +202,8 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
GlobalSearchScope scope = GlobalSearchScope.allScope(project);
|
GlobalSearchScope scope = GlobalSearchScope.allScope(project);
|
||||||
Collection<String> functionNames = namesCache.getAllTopLevelFunctionNames();
|
Collection<String> functionNames = namesCache.getAllTopLevelFunctionNames();
|
||||||
|
|
||||||
BindingContext resolutionContext =
|
BindingContext resolutionContext = WholeProjectAnalyzerFacade.getLazyResolveContext(
|
||||||
WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile)position.getContainingFile()).getBindingContext();
|
(JetFile) position.getContainingFile(), expression);
|
||||||
|
|
||||||
for (String name : functionNames) {
|
for (String name : functionNames) {
|
||||||
if (name.contains(actualPrefix)) {
|
if (name.contains(actualPrefix)) {
|
||||||
@@ -223,9 +220,9 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
private static void addClasses(
|
private static void addClasses(
|
||||||
@NotNull CompletionParameters parameters,
|
@NotNull CompletionParameters parameters,
|
||||||
@NotNull final CompletionResultSet result,
|
@NotNull final CompletionResultSet result,
|
||||||
@NotNull final CompletionSession session
|
@NotNull final CompletionSession session,
|
||||||
) {
|
BindingContext jetContext) {
|
||||||
JetClassCompletionContributor.addClasses(parameters, result, new Consumer<LookupElement>() {
|
JetClassCompletionContributor.addClasses(parameters, result, jetContext, new Consumer<LookupElement>() {
|
||||||
@Override
|
@Override
|
||||||
public void consume(@NotNull LookupElement element) {
|
public void consume(@NotNull LookupElement element) {
|
||||||
addCompletionToResult(result, element, session);
|
addCompletionToResult(result, element, session);
|
||||||
@@ -233,7 +230,7 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean shouldRunTypeCompletionOnly(PsiElement position, JetSimpleNameReference jetReference) {
|
private static boolean shouldRunTypeCompletionOnly(PsiElement position, @NotNull JetSimpleNameReference jetReference) {
|
||||||
// Check that completion in the type annotation context and if there's a qualified
|
// Check that completion in the type annotation context and if there's a qualified
|
||||||
// expression we are at first of it
|
// expression we are at first of it
|
||||||
JetTypeReference typeReference = PsiTreeUtil.getParentOfType(position, JetTypeReference.class);
|
JetTypeReference typeReference = PsiTreeUtil.getParentOfType(position, JetTypeReference.class);
|
||||||
@@ -245,7 +242,7 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean shouldRunTopLevelCompletion(@NotNull CompletionParameters parameters, CompletionSession session) {
|
private static boolean shouldRunTopLevelCompletion(@NotNull CompletionParameters parameters, @NotNull CompletionSession session) {
|
||||||
if (session.customInvocationCount == 0) {
|
if (session.customInvocationCount == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -263,7 +260,7 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean shouldRunExtensionsCompletion(CompletionParameters parameters, String prefix, CompletionSession session) {
|
private static boolean shouldRunExtensionsCompletion(@NotNull CompletionParameters parameters, @NotNull String prefix, @NotNull CompletionSession session) {
|
||||||
if (session.customInvocationCount == 0 && prefix.length() < 3) {
|
if (session.customInvocationCount == 0 && prefix.length() < 3) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -312,7 +309,7 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
session.isSomethingAdded = true;
|
session.isSomethingAdded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isVisibleElement(LookupElement element, CompletionSession session) {
|
private static boolean isVisibleElement(@NotNull LookupElement element, @NotNull CompletionSession session) {
|
||||||
if (session.inDescriptor != null) {
|
if (session.inDescriptor != null) {
|
||||||
if (element.getObject() instanceof JetLookupObject) {
|
if (element.getObject() instanceof JetLookupObject) {
|
||||||
JetLookupObject jetObject = (JetLookupObject)element.getObject();
|
JetLookupObject jetObject = (JetLookupObject)element.getObject();
|
||||||
@@ -324,14 +321,16 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isVisibleDescriptor(DeclarationDescriptor descriptor, CompletionSession session) {
|
private static boolean isVisibleDescriptor(DeclarationDescriptor descriptor, @NotNull CompletionSession session) {
|
||||||
if (session.customInvocationCount >= 2) {
|
if (session.customInvocationCount >= 2) {
|
||||||
// Show everything if user insist on showing completion list
|
// Show everything if user insist on showing completion list
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor instanceof DeclarationDescriptorWithVisibility) {
|
if (descriptor instanceof DeclarationDescriptorWithVisibility) {
|
||||||
return Visibilities.isVisible((DeclarationDescriptorWithVisibility)descriptor, session.inDescriptor);
|
if (session.inDescriptor != null) {
|
||||||
|
return Visibilities.isVisible((DeclarationDescriptorWithVisibility)descriptor, session.inDescriptor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -341,13 +340,10 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
private static LookupElement[] getReferenceVariants(
|
private static LookupElement[] getReferenceVariants(
|
||||||
@NotNull JetSimpleNameReference reference,
|
@NotNull JetSimpleNameReference reference,
|
||||||
@NotNull final CompletionResultSet result,
|
@NotNull final CompletionResultSet result,
|
||||||
@NotNull final CompletionSession session
|
@NotNull final CompletionSession session,
|
||||||
|
BindingContext jetContext
|
||||||
) {
|
) {
|
||||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(
|
Collection<DeclarationDescriptor> descriptors = TipsManager.getReferenceVariants(reference.getExpression(), jetContext);
|
||||||
(JetFile)reference.getExpression().getContainingFile())
|
|
||||||
.getBindingContext();
|
|
||||||
|
|
||||||
Collection<DeclarationDescriptor> descriptors = TipsManager.getReferenceVariants(reference.getExpression(), bindingContext);
|
|
||||||
|
|
||||||
Collection<DeclarationDescriptor> checkedDescriptors = Collections2.filter(descriptors, new Predicate<DeclarationDescriptor>() {
|
Collection<DeclarationDescriptor> checkedDescriptors = Collections2.filter(descriptors, new Predicate<DeclarationDescriptor>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -360,6 +356,6 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return DescriptorLookupConverter.collectLookupElements(bindingContext, checkedDescriptors);
|
return DescriptorLookupConverter.collectLookupElements(jetContext, checkedDescriptors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -24,7 +24,10 @@ import com.intellij.psi.PsiElement;
|
|||||||
import com.intellij.util.Consumer;
|
import com.intellij.util.Consumer;
|
||||||
import com.intellij.util.ProcessingContext;
|
import com.intellij.util.ProcessingContext;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special contributor for getting completion of type for extensions receiver.
|
* Special contributor for getting completion of type for extensions receiver.
|
||||||
@@ -38,8 +41,11 @@ public class JetExtensionReceiverTypeContributor extends CompletionContributor {
|
|||||||
ProcessingContext context,
|
ProcessingContext context,
|
||||||
final @NotNull CompletionResultSet result
|
final @NotNull CompletionResultSet result
|
||||||
) {
|
) {
|
||||||
|
BindingContext jetContext = WholeProjectAnalyzerFacade
|
||||||
|
.getLazyResolveContext((JetFile) parameters.getPosition().getContainingFile(), null);
|
||||||
|
|
||||||
if (parameters.getInvocationCount() > 0 || parameters.getCompletionType() == CompletionType.CLASS_NAME) {
|
if (parameters.getInvocationCount() > 0 || parameters.getCompletionType() == CompletionType.CLASS_NAME) {
|
||||||
JetClassCompletionContributor.addClasses(parameters, result, new Consumer<LookupElement>() {
|
JetClassCompletionContributor.addClasses(parameters, result, jetContext, new Consumer<LookupElement>() {
|
||||||
@Override
|
@Override
|
||||||
public void consume(@NotNull LookupElement element) {
|
public void consume(@NotNull LookupElement element) {
|
||||||
result.addElement(element);
|
result.addElement(element);
|
||||||
|
|||||||
@@ -71,12 +71,11 @@ public class JetPackagesContributor extends CompletionContributor {
|
|||||||
int prefixLength = parameters.getOffset() - simpleNameReference.getExpression().getTextOffset();
|
int prefixLength = parameters.getOffset() - simpleNameReference.getExpression().getTextOffset();
|
||||||
result = result.withPrefixMatcher(new PlainPrefixMatcher(name.substring(0, prefixLength)));
|
result = result.withPrefixMatcher(new PlainPrefixMatcher(name.substring(0, prefixLength)));
|
||||||
|
|
||||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(
|
BindingContext bindingContext = WholeProjectAnalyzerFacade.getLazyResolveContext(
|
||||||
(JetFile)namespaceHeader.getContainingFile())
|
(JetFile) namespaceHeader.getContainingFile(), simpleNameReference.getExpression());
|
||||||
.getBindingContext();
|
|
||||||
|
|
||||||
for (LookupElement variant : DescriptorLookupConverter.collectLookupElements(
|
for (LookupElement variant : DescriptorLookupConverter.collectLookupElements(
|
||||||
bindingContext, TipsManager.getReferenceVariants(namespaceHeader, bindingContext))) {
|
bindingContext, TipsManager.getPackageReferenceVariants(simpleNameReference.getExpression(), bindingContext))) {
|
||||||
if (!variant.getLookupString().contains(DUMMY_IDENTIFIER)) {
|
if (!variant.getLookupString().contains(DUMMY_IDENTIFIER)) {
|
||||||
result.addElement(variant);
|
result.addElement(variant);
|
||||||
}
|
}
|
||||||
@@ -92,5 +91,6 @@ public class JetPackagesContributor extends CompletionContributor {
|
|||||||
public void beforeCompletion(@NotNull CompletionInitializationContext context) {
|
public void beforeCompletion(@NotNull CompletionInitializationContext context) {
|
||||||
// Will need to filter this dummy identifier to avoid showing it in completion
|
// Will need to filter this dummy identifier to avoid showing it in completion
|
||||||
context.setDummyIdentifier(DUMMY_IDENTIFIER);
|
context.setDummyIdentifier(DUMMY_IDENTIFIER);
|
||||||
|
// context.setDummyIdentifier(CompletionInitializationContext.DUMMY_IDENTIFIER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,33 +18,43 @@ package org.jetbrains.jet.plugin.project;
|
|||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.openapi.diagnostic.Logger;
|
import com.intellij.openapi.diagnostic.Logger;
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.util.Key;
|
import com.intellij.openapi.util.Key;
|
||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
import com.intellij.psi.PsiManager;
|
import com.intellij.psi.PsiManager;
|
||||||
import com.intellij.psi.impl.PsiModificationTrackerImpl;
|
import com.intellij.psi.impl.PsiModificationTrackerImpl;
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
import com.intellij.psi.util.CachedValue;
|
import com.intellij.psi.util.CachedValue;
|
||||||
import com.intellij.psi.util.CachedValueProvider;
|
import com.intellij.psi.util.CachedValueProvider;
|
||||||
import com.intellij.psi.util.CachedValuesManager;
|
import com.intellij.psi.util.CachedValuesManager;
|
||||||
import com.intellij.psi.util.PsiModificationTracker;
|
import com.intellij.psi.util.PsiModificationTracker;
|
||||||
import com.intellij.util.Function;
|
import com.intellij.util.Function;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
||||||
|
import org.jetbrains.jet.di.InjectorForJavaDescriptorResolver;
|
||||||
|
import org.jetbrains.jet.lang.BuiltinsScopeExtensionMode;
|
||||||
|
import org.jetbrains.jet.lang.DefaultModuleConfiguration;
|
||||||
|
import org.jetbrains.jet.lang.ModuleConfiguration;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
import org.jetbrains.jet.lang.psi.JetImportDirective;
|
||||||
import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter;
|
import org.jetbrains.jet.lang.psi.JetPsiFactory;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
import org.jetbrains.jet.lang.resolve.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BodiesResolveContext;
|
import org.jetbrains.jet.lang.resolve.java.*;
|
||||||
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
|
import org.jetbrains.jet.lang.resolve.lazy.FileBasedDeclarationProviderFactory;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JetFilesProvider;
|
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
|
||||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||||
|
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pavel Talanov
|
* @author Pavel Talanov
|
||||||
@@ -55,6 +65,7 @@ public final class AnalyzerFacadeWithCache {
|
|||||||
|
|
||||||
private final static Key<CachedValue<AnalyzeExhaust>> ANALYZE_EXHAUST_HEADERS = Key.create("ANALYZE_EXHAUST_HEADERS");
|
private final static Key<CachedValue<AnalyzeExhaust>> ANALYZE_EXHAUST_HEADERS = Key.create("ANALYZE_EXHAUST_HEADERS");
|
||||||
private final static Key<CachedValue<AnalyzeExhaust>> ANALYZE_EXHAUST_FULL = Key.create("ANALYZE_EXHAUST_FULL");
|
private final static Key<CachedValue<AnalyzeExhaust>> ANALYZE_EXHAUST_FULL = Key.create("ANALYZE_EXHAUST_FULL");
|
||||||
|
private final static Key<CachedValue<ResolveSession>> ANALYZE_EXHAUST_LAZY_FULL = Key.create("ANALYZE_EXHAUST_FULL");
|
||||||
|
|
||||||
private static final Object lock = new Object();
|
private static final Object lock = new Object();
|
||||||
public static final Function<JetFile, Collection<JetFile>> SINGLE_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetFile>>() {
|
public static final Function<JetFile, Collection<JetFile>> SINGLE_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetFile>>() {
|
||||||
@@ -67,7 +78,6 @@ public final class AnalyzerFacadeWithCache {
|
|||||||
private AnalyzerFacadeWithCache() {
|
private AnalyzerFacadeWithCache() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Analyze project with string cache for given file. Given file will be fully analyzed.
|
* Analyze project with string cache for given file. Given file will be fully analyzed.
|
||||||
*
|
*
|
||||||
@@ -88,8 +98,6 @@ public final class AnalyzerFacadeWithCache {
|
|||||||
@Override
|
@Override
|
||||||
public Result<AnalyzeExhaust> compute() {
|
public Result<AnalyzeExhaust> compute() {
|
||||||
try {
|
try {
|
||||||
// System.out.println("===============ReCache - In-Block==============");
|
|
||||||
|
|
||||||
// Collect context for headers first
|
// Collect context for headers first
|
||||||
AnalyzeExhaust analyzeExhaustHeaders = analyzeHeadersWithCacheOnFile(file, declarationProvider);
|
AnalyzeExhaust analyzeExhaustHeaders = analyzeHeadersWithCacheOnFile(file, declarationProvider);
|
||||||
|
|
||||||
@@ -149,7 +157,6 @@ public final class AnalyzerFacadeWithCache {
|
|||||||
CachedValuesManager.getManager(fileToCache.getProject()).createCachedValue(new CachedValueProvider<AnalyzeExhaust>() {
|
CachedValuesManager.getManager(fileToCache.getProject()).createCachedValue(new CachedValueProvider<AnalyzeExhaust>() {
|
||||||
@Override
|
@Override
|
||||||
public Result<AnalyzeExhaust> compute() {
|
public Result<AnalyzeExhaust> compute() {
|
||||||
// System.out.println("===============ReCache - OUT-OF-BLOCK==============");
|
|
||||||
AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(fileToCache)
|
AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(fileToCache)
|
||||||
.analyzeFiles(fileToCache.getProject(),
|
.analyzeFiles(fileToCache.getProject(),
|
||||||
declarationProvider.fun(fileToCache),
|
declarationProvider.fun(fileToCache),
|
||||||
@@ -169,4 +176,80 @@ public final class AnalyzerFacadeWithCache {
|
|||||||
DiagnosticUtils.throwIfRunningOnServer(e);
|
DiagnosticUtils.throwIfRunningOnServer(e);
|
||||||
LOG.error(e);
|
LOG.error(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Object lazyLock = new Object();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static ResolveSession getLazyResolveSession(@NotNull final JetFile file) {
|
||||||
|
synchronized (lazyLock) {
|
||||||
|
final Project fileProject = file.getProject();
|
||||||
|
CachedValue<ResolveSession> bindingContextCachedValue = file.getUserData(ANALYZE_EXHAUST_LAZY_FULL);
|
||||||
|
if (bindingContextCachedValue == null) {
|
||||||
|
bindingContextCachedValue =
|
||||||
|
CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<ResolveSession>() {
|
||||||
|
@Override
|
||||||
|
public Result<ResolveSession> compute() {
|
||||||
|
ModuleDescriptor javaModule = new ModuleDescriptor(Name.special("<java module>"));
|
||||||
|
|
||||||
|
InjectorForJavaDescriptorResolver injector = new InjectorForJavaDescriptorResolver(
|
||||||
|
fileProject, new BindingTraceContext(), javaModule, BuiltinsScopeExtensionMode.ALL);
|
||||||
|
|
||||||
|
List<JetFile> files = JetFilesProvider.getInstance(fileProject).allInScope(GlobalSearchScope.allScope(fileProject));
|
||||||
|
|
||||||
|
// Given file can differ from the original because it can be a virtual copy with some modifications
|
||||||
|
JetFile originalFile = (JetFile) file.getOriginalFile();
|
||||||
|
files.remove(originalFile);
|
||||||
|
files.add(file);
|
||||||
|
|
||||||
|
final PsiClassFinder psiClassFinder = injector.getPsiClassFinder();
|
||||||
|
|
||||||
|
// TODO: Replace with stub declaration provider
|
||||||
|
final FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(files, new Predicate<FqName>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(FqName fqName) {
|
||||||
|
return psiClassFinder.findPsiPackage(fqName) != null || new FqName("jet").equals(fqName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver();
|
||||||
|
|
||||||
|
ModuleConfiguration moduleConfiguration = new ModuleConfiguration() {
|
||||||
|
@Override
|
||||||
|
public void addDefaultImports(@NotNull Collection<JetImportDirective> directives) {
|
||||||
|
final Collection<ImportPath> defaultImports = Lists.newArrayList(JavaBridgeConfiguration.DEFAULT_JAVA_IMPORTS);
|
||||||
|
defaultImports.addAll(Arrays.asList(DefaultModuleConfiguration.DEFAULT_JET_IMPORTS));
|
||||||
|
|
||||||
|
for (ImportPath defaultJetImport : defaultImports) {
|
||||||
|
directives.add(JetPsiFactory.createImportDirective(fileProject, defaultJetImport));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void extendNamespaceScope(
|
||||||
|
@NotNull BindingTrace trace,
|
||||||
|
@NotNull NamespaceDescriptor namespaceDescriptor,
|
||||||
|
@NotNull WritableScope namespaceMemberScope
|
||||||
|
) {
|
||||||
|
FqName fqName = DescriptorUtils.getFQName(namespaceDescriptor).toSafe();
|
||||||
|
if (new FqName("jet").equals(fqName)) {
|
||||||
|
namespaceMemberScope.importScope(JetStandardLibrary.getInstance().getLibraryScope());
|
||||||
|
}
|
||||||
|
if (psiClassFinder.findPsiPackage(fqName) != null) {
|
||||||
|
JavaPackageScope javaPackageScope = javaDescriptorResolver.getJavaPackageScope(fqName, namespaceDescriptor);
|
||||||
|
namespaceMemberScope.importScope(javaPackageScope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ModuleDescriptor lazyModule = new ModuleDescriptor(Name.special("<lazy module>"));
|
||||||
|
ResolveSession resolveSession = new ResolveSession(fileProject, lazyModule, moduleConfiguration, declarationProviderFactory);
|
||||||
|
|
||||||
|
return new Result<ResolveSession>(resolveSession, PsiModificationTracker.MODIFICATION_COUNT);
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
file.putUserData(ANALYZE_EXHAUST_LAZY_FULL, bindingContextCachedValue);
|
||||||
|
}
|
||||||
|
return bindingContextCachedValue.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,20 +17,23 @@
|
|||||||
package org.jetbrains.jet.plugin.project;
|
package org.jetbrains.jet.plugin.project;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JetFilesProvider;
|
import org.jetbrains.jet.lang.resolve.java.JetFilesProvider;
|
||||||
|
import org.jetbrains.jet.lang.resolve.lazy.LazyBindingContextUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
|
||||||
|
|
||||||
import static org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache.analyzeFileWithCache;
|
import static org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache.analyzeFileWithCache;
|
||||||
|
import static org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache.getLazyResolveSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public final class WholeProjectAnalyzerFacade {
|
public final class WholeProjectAnalyzerFacade {
|
||||||
|
|
||||||
/**
|
|
||||||
* Forbid creating
|
|
||||||
*/
|
|
||||||
private WholeProjectAnalyzerFacade() {
|
private WholeProjectAnalyzerFacade() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,4 +41,17 @@ public final class WholeProjectAnalyzerFacade {
|
|||||||
public static AnalyzeExhaust analyzeProjectWithCacheOnAFile(@NotNull JetFile file) {
|
public static AnalyzeExhaust analyzeProjectWithCacheOnAFile(@NotNull JetFile file) {
|
||||||
return analyzeFileWithCache(file, JetFilesProvider.getInstance(file.getProject()).sampleToAllFilesInModule());
|
return analyzeFileWithCache(file, JetFilesProvider.getInstance(file.getProject()).sampleToAllFilesInModule());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static ResolveSession getLazyResolveSessionForFile(@NotNull JetFile file) {
|
||||||
|
return getLazyResolveSession(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static BindingContext getLazyResolveContext(@NotNull JetFile file, @Nullable JetExpression expression) {
|
||||||
|
ResolveSession resolveSession = getLazyResolveSessionForFile(file);
|
||||||
|
return expression != null ?
|
||||||
|
LazyBindingContextUtils.getExpressionBindingContext(resolveSession, expression) :
|
||||||
|
resolveSession.getBindingContext();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user