KT-2724 No completion in class initializers
#KT-2724 Fixed
This commit is contained in:
@@ -112,8 +112,6 @@ public class MutableClassDescriptor extends MutableClassDescriptorLite implement
|
||||
return primaryConstructor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@NotNull
|
||||
public Set<SimpleFunctionDescriptor> getFunctions() {
|
||||
return functions;
|
||||
|
||||
@@ -26,7 +26,7 @@ import java.util.List;
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public interface JetClassOrObject extends PsiNameIdentifierOwner, JetDeclarationContainer, JetElement, JetModifierListOwner {
|
||||
public interface JetClassOrObject extends PsiNameIdentifierOwner, JetDeclarationContainer, JetElement, JetModifierListOwner, JetDeclaration {
|
||||
@Nullable
|
||||
JetDelegationSpecifierList getDelegationSpecifierList();
|
||||
|
||||
|
||||
@@ -352,4 +352,22 @@ public class JetPsiUtil {
|
||||
JetMultiDeclarationEntry multiDeclarationEntry = (JetMultiDeclarationEntry) declaration;
|
||||
return !(multiDeclarationEntry.getParent().getParent() instanceof JetForExpression);
|
||||
}
|
||||
|
||||
public static PsiElement getTopmostParentOfTypes(@Nullable PsiElement element, @NotNull Class<? extends PsiElement>... parentTypes) {
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiElement result = null;
|
||||
PsiElement parent = element.getParent();
|
||||
while (parent != null) {
|
||||
if (PsiTreeUtil.instanceOf(parent, parentTypes)) {
|
||||
result = parent;
|
||||
}
|
||||
|
||||
parent = parent.getParent();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.google.common.collect.Sets;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.containers.Queue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
|
||||
@@ -322,12 +323,18 @@ public class BodyResolver {
|
||||
}
|
||||
|
||||
private void resolveAnonymousInitializers(JetClassOrObject jetClassOrObject, MutableClassDescriptor classDescriptor) {
|
||||
if (!context.completeAnalysisNeeded(jetClassOrObject)) return;
|
||||
resolveAnonymousInitializers(jetClassOrObject, classDescriptor.getUnsubstitutedPrimaryConstructor(),
|
||||
classDescriptor.getScopeForInitializers());
|
||||
}
|
||||
|
||||
public void resolveAnonymousInitializers(JetClassOrObject jetClassOrObject,
|
||||
@Nullable ConstructorDescriptor primaryConstructor,
|
||||
@NotNull JetScope scopeForInitializers) {
|
||||
if (!context.completeAnalysisNeeded(jetClassOrObject)) {
|
||||
return;
|
||||
}
|
||||
List<JetClassInitializer> anonymousInitializers = jetClassOrObject.getAnonymousInitializers();
|
||||
if (classDescriptor.getUnsubstitutedPrimaryConstructor() != null) {
|
||||
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||
assert primaryConstructor != null;
|
||||
final JetScope scopeForInitializers = classDescriptor.getScopeForInitializers();
|
||||
if (primaryConstructor != null) {
|
||||
for (JetClassInitializer anonymousInitializer : anonymousInitializers) {
|
||||
expressionTypingServices.getType(scopeForInitializers, anonymousInitializer.getBody(), NO_EXPECTED_TYPE, DataFlowInfo.EMPTY, trace);
|
||||
}
|
||||
|
||||
+61
-26
@@ -18,7 +18,6 @@ package org.jetbrains.jet.lang.resolve.lazy;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -39,8 +38,6 @@ import java.util.*;
|
||||
* @author Nikolay Krasko
|
||||
*/
|
||||
public class ResolveSessionUtils {
|
||||
private static final Logger LOG = Logger.getInstance("#" + ResolveSessionUtils.class.getName());
|
||||
|
||||
private ResolveSessionUtils() {
|
||||
}
|
||||
|
||||
@@ -90,34 +87,33 @@ public class ResolveSessionUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static @NotNull BindingContext resolveToExpression(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) {
|
||||
public static
|
||||
@NotNull
|
||||
BindingContext resolveToExpression(
|
||||
@NotNull final 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());
|
||||
@SuppressWarnings("unchecked") PsiElement topmostCandidateForAdditionalResolve = JetPsiUtil.getTopmostParentOfTypes(expression,
|
||||
JetNamedFunction.class, JetClassInitializer.class);
|
||||
|
||||
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);
|
||||
if (topmostCandidateForAdditionalResolve != null) {
|
||||
if (topmostCandidateForAdditionalResolve instanceof JetNamedFunction) {
|
||||
functionAdditionalResolve(resolveSession, (JetNamedFunction) topmostCandidateForAdditionalResolve, trace, file);
|
||||
}
|
||||
else if (topmostCandidateForAdditionalResolve instanceof JetClassInitializer) {
|
||||
initializerAdditionalResolve(resolveSession, (JetClassInitializer) topmostCandidateForAdditionalResolve, trace, file);
|
||||
}
|
||||
else {
|
||||
LOG.warn(String.format("Not expected parent for function: %s in %s",
|
||||
namedFunction.getName(), namedFunction.getContainingFile()));
|
||||
assert false : "Invalid type of the topmost parent";
|
||||
}
|
||||
|
||||
return trace.getBindingContext();
|
||||
}
|
||||
|
||||
// Setup resolution scope explicitly
|
||||
if (trace.getBindingContext().get(BindingContext.RESOLUTION_SCOPE, expression) == null) {
|
||||
JetScope scope = getExpressionMemberScope(resolveSession, expression);
|
||||
if (scope != null) {
|
||||
@@ -128,7 +124,45 @@ public class ResolveSessionUtils {
|
||||
return trace.getBindingContext();
|
||||
}
|
||||
|
||||
private static JetScope getExpressionOuterScope(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) {
|
||||
private static void functionAdditionalResolve(
|
||||
ResolveSession resolveSession,
|
||||
JetNamedFunction namedFunction,
|
||||
DelegatingBindingTrace trace,
|
||||
JetFile file
|
||||
) {
|
||||
BodyResolver bodyResolver = createBodyResolver(trace, file);
|
||||
JetScope scope = resolveSession.getResolutionScope(namedFunction);
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) resolveSession.resolveToDescriptor(namedFunction);
|
||||
bodyResolver.resolveFunctionBody(trace, namedFunction, functionDescriptor, scope);
|
||||
}
|
||||
|
||||
private static boolean initializerAdditionalResolve(
|
||||
ResolveSession resolveSession,
|
||||
JetClassInitializer classInitializer,
|
||||
DelegatingBindingTrace trace,
|
||||
JetFile file
|
||||
) {
|
||||
BodyResolver bodyResolver = createBodyResolver(trace, file);
|
||||
JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(classInitializer, JetClassOrObject.class);
|
||||
LazyClassDescriptor classOrObjectDescriptor = (LazyClassDescriptor) resolveSession.resolveToDescriptor(classOrObject);
|
||||
bodyResolver.resolveAnonymousInitializers(classOrObject, classOrObjectDescriptor.getUnsubstitutedPrimaryConstructor(),
|
||||
classOrObjectDescriptor.getScopeForPropertyInitializerResolution());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static BodyResolver createBodyResolver(DelegatingBindingTrace trace, JetFile file, EmptyBodyResolveContext bodyResolveContext) {
|
||||
TopDownAnalysisParameters parameters = new TopDownAnalysisParameters(
|
||||
Predicates.<PsiFile>alwaysTrue(), false, true, Collections.<AnalyzerScriptParameter>emptyList());
|
||||
InjectorForBodyResolve bodyResolve = new InjectorForBodyResolve(file.getProject(), parameters, trace, bodyResolveContext);
|
||||
return bodyResolve.getBodyResolver();
|
||||
}
|
||||
|
||||
private static BodyResolver createBodyResolver(DelegatingBindingTrace trace, JetFile file) {
|
||||
return createBodyResolver(trace, file, new EmptyBodyResolveContext());
|
||||
}
|
||||
|
||||
private static JetScope getExpressionResolutionScope(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) {
|
||||
JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class);
|
||||
// DeclarationDescriptor descriptor = resolveToDescriptor(parentDeclaration);
|
||||
return resolveSession.getResolutionScope(parentDeclaration);
|
||||
@@ -145,7 +179,7 @@ public class ResolveSessionUtils {
|
||||
JetUserType qualifier = ((JetUserType) expression.getParent()).getQualifier();
|
||||
if (qualifier != null) {
|
||||
Collection<? extends DeclarationDescriptor> descriptors = qualifiedExpressionResolver
|
||||
.lookupDescriptorsForUserType(qualifier, getExpressionOuterScope(resolveSession, expression), trace);
|
||||
.lookupDescriptorsForUserType(qualifier, getExpressionResolutionScope(resolveSession, expression), trace);
|
||||
|
||||
for (DeclarationDescriptor descriptor : descriptors) {
|
||||
if (descriptor instanceof LazyPackageDescriptor) {
|
||||
@@ -164,7 +198,8 @@ public class ResolveSessionUtils {
|
||||
JetExpression element = ((JetDotQualifiedExpression) expression.getParent()).getReceiverExpression();
|
||||
String name = ((JetFile) expression.getContainingFile()).getPackageName();
|
||||
|
||||
NamespaceDescriptor filePackage = name != null ? resolveSession.getPackageDescriptorByFqName(new FqName(name)) : rootPackage;
|
||||
NamespaceDescriptor filePackage =
|
||||
name != null ? resolveSession.getPackageDescriptorByFqName(new FqName(name)) : rootPackage;
|
||||
assert filePackage != null : "File package should be already resolved and be found";
|
||||
|
||||
JetScope scope = filePackage.getMemberScope();
|
||||
@@ -194,7 +229,7 @@ public class ResolveSessionUtils {
|
||||
JetNamespaceHeader namespaceHeader = PsiTreeUtil.getParentOfType(expression, JetNamespaceHeader.class, false);
|
||||
if (namespaceHeader != null) {
|
||||
NamespaceDescriptor packageDescriptor = resolveSession.getPackageDescriptorByFqName(
|
||||
namespaceHeader.getParentFqName((JetReferenceExpression)expression));
|
||||
namespaceHeader.getParentFqName((JetReferenceExpression) expression));
|
||||
if (packageDescriptor != null) {
|
||||
return packageDescriptor.getMemberScope();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
val testExternal
|
||||
|
||||
class Some(testParam : Int) {
|
||||
private val myVal : Int
|
||||
|
||||
{
|
||||
val testing = 12
|
||||
myVal = test<caret>
|
||||
}
|
||||
}
|
||||
|
||||
// EXIST: testParam, testExternal, testing
|
||||
@@ -0,0 +1,11 @@
|
||||
val some = 12
|
||||
class Some(someParam : Int) {
|
||||
{
|
||||
fun internalFun(someInternal : Int) : Int {
|
||||
return some<caret>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EXIST: some, someInternal, someParam
|
||||
|
||||
@@ -88,10 +88,18 @@ public class JetBasicCompletionTest extends JetCompletionTestBase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testInClassInitializer() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testInEmptyImport() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testInFunInClassInitializer() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testInImport() {
|
||||
doTest();
|
||||
}
|
||||
@@ -100,7 +108,6 @@ public class JetBasicCompletionTest extends JetCompletionTestBase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
public void testInMiddleOfNamespace() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user