@NotNull /*package*/ MemberScope getMemberScopeDeclaredIn( @NotNull KtDeclaration declaration, @NotNull LookupLocation location) { KtDeclaration parentDeclaration = KtStubbedPsiUtil.getContainingDeclaration(declaration); boolean isTopLevel = parentDeclaration == null; if (isTopLevel) { // for top level declarations we search directly in package because of // possible conflicts with imports FqName fqName = ((KtFile) declaration.getContainingFile()).getPackageFqName(); LazyPackageDescriptor packageDescriptor = topLevelDescriptorProvider.getPackageFragment(fqName); assert packageDescriptor != null; return packageDescriptor.getMemberScope(); } else { if (parentDeclaration instanceof KtClassOrObject) { return getClassDescriptor((KtClassOrObject) parentDeclaration, location) .getUnsubstitutedMemberScope(); } else if (parentDeclaration instanceof KtScript) { return getScriptDescriptor((KtScript) parentDeclaration, location) .getUnsubstitutedMemberScope(); } else { throw new IllegalStateException( "Don't call this method for local declarations: " + declaration + "\n" + PsiUtilsKt.getElementTextWithContext(declaration)); } } }
@NotNull private DeclarationDescriptor resolveToDescriptor( @NotNull KtDeclaration declaration, final boolean track) { DeclarationDescriptor result = declaration.accept( new KtVisitor<DeclarationDescriptor, Void>() { @NotNull private LookupLocation lookupLocationFor( @NotNull KtDeclaration declaration, boolean isTopLevel) { return isTopLevel && track ? new KotlinLookupLocation(declaration) : NoLookupLocation.WHEN_RESOLVE_DECLARATION; } @Override public DeclarationDescriptor visitClass(@NotNull KtClass klass, Void data) { return getClassDescriptor(klass, lookupLocationFor(klass, klass.isTopLevel())); } @Override public DeclarationDescriptor visitObjectDeclaration( @NotNull KtObjectDeclaration declaration, Void data) { return getClassDescriptor( declaration, lookupLocationFor(declaration, declaration.isTopLevel())); } @Override public DeclarationDescriptor visitTypeParameter( @NotNull KtTypeParameter parameter, Void data) { KtTypeParameterListOwner ownerElement = PsiTreeUtil.getParentOfType(parameter, KtTypeParameterListOwner.class); assert ownerElement != null : "Owner not found for type parameter: " + parameter.getText(); DeclarationDescriptor ownerDescriptor = resolveToDescriptor(ownerElement, /*track =*/ false); List<TypeParameterDescriptor> typeParameters; if (ownerDescriptor instanceof CallableDescriptor) { CallableDescriptor callableDescriptor = (CallableDescriptor) ownerDescriptor; typeParameters = callableDescriptor.getTypeParameters(); } else if (ownerDescriptor instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) ownerDescriptor; typeParameters = classDescriptor.getTypeConstructor().getParameters(); } else { throw new IllegalStateException( "Unknown owner kind for a type parameter: " + ownerDescriptor); } Name name = parameter.getNameAsSafeName(); for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) { if (typeParameterDescriptor.getName().equals(name)) { return typeParameterDescriptor; } } throw new IllegalStateException( "Type parameter " + name + " not found for " + ownerDescriptor); } @Override public DeclarationDescriptor visitNamedFunction( @NotNull KtNamedFunction function, Void data) { LookupLocation location = lookupLocationFor(function, function.isTopLevel()); MemberScope scopeForDeclaration = getMemberScopeDeclaredIn(function, location); scopeForDeclaration.getContributedFunctions(function.getNameAsSafeName(), location); return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, function); } @Override public DeclarationDescriptor visitParameter( @NotNull KtParameter parameter, Void data) { PsiElement grandFather = parameter.getParent().getParent(); if (grandFather instanceof KtPrimaryConstructor) { KtClassOrObject jetClass = ((KtPrimaryConstructor) grandFather).getContainingClassOrObject(); // This is a primary constructor parameter ClassDescriptor classDescriptor = getClassDescriptor(jetClass, lookupLocationFor(jetClass, false)); if (parameter.hasValOrVar()) { classDescriptor .getDefaultType() .getMemberScope() .getContributedVariables( parameter.getNameAsSafeName(), lookupLocationFor(parameter, false)); return getBindingContext() .get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter); } else { ConstructorDescriptor constructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); assert constructor != null : "There are constructor parameters found, so a constructor should also exist"; constructor.getValueParameters(); return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter); } } else if (grandFather instanceof KtNamedFunction) { FunctionDescriptor function = (FunctionDescriptor) visitNamedFunction((KtNamedFunction) grandFather, data); function.getValueParameters(); return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter); } else if (grandFather instanceof KtSecondaryConstructor) { ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) visitSecondaryConstructor((KtSecondaryConstructor) grandFather, data); constructorDescriptor.getValueParameters(); return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter); } else { // TODO: support parameters in accessors and other places(?) return super.visitParameter(parameter, data); } } @Override public DeclarationDescriptor visitSecondaryConstructor( @NotNull KtSecondaryConstructor constructor, Void data) { getClassDescriptor( (KtClassOrObject) constructor.getParent().getParent(), lookupLocationFor(constructor, false)) .getConstructors(); return getBindingContext().get(BindingContext.CONSTRUCTOR, constructor); } @Override public DeclarationDescriptor visitPrimaryConstructor( @NotNull KtPrimaryConstructor constructor, Void data) { getClassDescriptor( constructor.getContainingClassOrObject(), lookupLocationFor(constructor, false)) .getConstructors(); return getBindingContext().get(BindingContext.CONSTRUCTOR, constructor); } @Override public DeclarationDescriptor visitProperty(@NotNull KtProperty property, Void data) { LookupLocation location = lookupLocationFor(property, property.isTopLevel()); MemberScope scopeForDeclaration = getMemberScopeDeclaredIn(property, location); scopeForDeclaration.getContributedVariables(property.getNameAsSafeName(), location); return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, property); } @Override public DeclarationDescriptor visitScript(@NotNull KtScript script, Void data) { return getScriptDescriptor(script, lookupLocationFor(script, true)); } @Override public DeclarationDescriptor visitKtElement(@NotNull KtElement element, Void data) { throw new IllegalArgumentException( "Unsupported declaration type: " + element + " " + PsiUtilsKt.getElementTextWithContext(element)); } }, null); if (result == null) { throw new NoDescriptorForDeclarationException(declaration); } return result; }