Support destructuring declarations in scripts and REPL

#KT-5620 In Progress
 #KT-15810 In Progress
This commit is contained in:
Mikhail Zarechenskiy
2017-05-24 16:32:33 +03:00
parent 0e31c14a86
commit 400ecd5e13
21 changed files with 333 additions and 46 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.cli.jvm.repl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry
import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
@@ -34,6 +35,9 @@ open class DelegatePackageMemberDeclarationProvider(var delegate: PackageMemberD
override fun getPropertyDeclarations(name: Name) = delegate.getPropertyDeclarations(name)
override fun getDestructuringDeclarationsEntries(name: Name): Collection<KtDestructuringDeclarationEntry> =
delegate.getDestructuringDeclarationsEntries(name)
override fun getClassOrObjectDeclarations(name: Name) = delegate.getClassOrObjectDeclarations(name)
override fun getTypeAliasDeclarations(name: Name) = delegate.getTypeAliasDeclarations(name)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -126,6 +126,7 @@ class SyntheticClassOrObjectDescriptor(
override fun getDeclarations(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): List<KtDeclaration> = emptyList()
override fun getFunctionDeclarations(name: Name): Collection<KtNamedFunction> = emptyList()
override fun getPropertyDeclarations(name: Name): Collection<KtProperty> = emptyList()
override fun getDestructuringDeclarationsEntries(name: Name): Collection<KtDestructuringDeclarationEntry> = emptyList()
override fun getClassOrObjectDeclarations(name: Name): Collection<KtClassLikeInfo> = emptyList()
override fun getTypeAliasDeclarations(name: Name): Collection<KtTypeAlias> = emptyList()
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -48,6 +48,8 @@ public interface BodiesResolveContext {
Map<KtNamedFunction, SimpleFunctionDescriptor> getFunctions();
@Mutable
Map<KtTypeAlias, TypeAliasDescriptor> getTypeAliases();
@Mutable
Map<KtDestructuringDeclarationEntry, PropertyDescriptor> getDestructuringDeclarationEntries();
@Nullable
LexicalScope getDeclaringScope(@NotNull KtDeclaration declaration);
@@ -110,6 +110,16 @@ class DeclarationsChecker(
identifierChecker.checkDeclaration(property, trace)
}
val destructuringDeclarations = bodiesResolveContext.destructuringDeclarationEntries.entries
.map { (entry, _) -> entry.parent }
.filterIsInstance<KtDestructuringDeclaration>()
.distinct()
for (multiDeclaration in destructuringDeclarations) {
modifiersChecker.checkModifiersForDestructuringDeclaration(multiDeclaration)
identifierChecker.checkDeclaration(multiDeclaration, trace)
}
for ((declaration, constructorDescriptor) in bodiesResolveContext.secondaryConstructors.entries) {
checkConstructorDeclaration(constructorDescriptor, declaration)
exposedChecker.checkFunction(declaration, constructorDescriptor)
@@ -51,6 +51,7 @@ import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor;
import org.jetbrains.kotlin.resolve.scopes.*;
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt;
import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
@@ -777,6 +778,50 @@ public class DescriptorResolver {
}
}
@NotNull
public PropertyDescriptor resolveDestructuringDeclarationEntryAsProperty(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull LexicalScope scopeForDeclarationResolution,
@NotNull LexicalScope scopeForInitializerResolution,
@NotNull KtDestructuringDeclarationEntry entry,
@NotNull BindingTrace trace,
@NotNull DataFlowInfo dataFlowInfo
) {
KtDestructuringDeclaration destructuringDeclaration = (KtDestructuringDeclaration) entry.getParent();
KtExpression initializer = destructuringDeclaration.getInitializer();
ExpressionTypingContext context = ExpressionTypingContext.newContext(
trace, scopeForDeclarationResolution, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE
);
ExpressionReceiver receiver = createReceiverForDestructuringDeclaration(destructuringDeclaration, context);
int componentIndex = destructuringDeclaration.getEntries().indexOf(entry);
KotlinType componentType = destructuringDeclarationResolver.resolveInitializer(entry, receiver, initializer, context, componentIndex);
return resolveAsPropertyDescriptor(
containingDeclaration,
scopeForDeclarationResolution,
scopeForInitializerResolution,
entry,
trace,
dataFlowInfo,
VariableAsPropertyInfo.Companion.createFromDestructuringDeclarationEntry(componentType));
}
private ExpressionReceiver createReceiverForDestructuringDeclaration(
@NotNull KtDestructuringDeclaration destructuringDeclaration,
@NotNull ExpressionTypingContext context
) {
KtExpression initializer = destructuringDeclaration.getInitializer();
if (initializer == null) return null;
KotlinType initializerType = expressionTypingServices.getTypeInfo(initializer, context).getType();
if (initializerType == null) return null;
return ExpressionReceiver.Companion.create(initializer, initializerType, context.trace.getBindingContext());
}
@NotNull
public PropertyDescriptor resolvePropertyDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@@ -786,16 +831,37 @@ public class DescriptorResolver {
@NotNull BindingTrace trace,
@NotNull DataFlowInfo dataFlowInfo
) {
KtModifierList modifierList = property.getModifierList();
boolean isVar = property.isVar();
return resolveAsPropertyDescriptor(
containingDeclaration,
scopeForDeclarationResolution,
scopeForInitializerResolution,
property,
trace,
dataFlowInfo,
VariableAsPropertyInfo.Companion.createFromProperty(property));
}
Visibility visibility = resolveVisibilityFromModifiers(property, getDefaultVisibility(property, containingDeclaration));
@NotNull
private PropertyDescriptor resolveAsPropertyDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull LexicalScope scopeForDeclarationResolution,
@NotNull LexicalScope scopeForInitializerResolution,
@NotNull KtVariableDeclaration variableDeclaration,
@NotNull BindingTrace trace,
@NotNull DataFlowInfo dataFlowInfo,
@NotNull VariableAsPropertyInfo propertyInfo
) {
KtModifierList modifierList = variableDeclaration.getModifierList();
boolean isVar = variableDeclaration.isVar();
Visibility visibility = resolveVisibilityFromModifiers(variableDeclaration, getDefaultVisibility(variableDeclaration, containingDeclaration));
Modality modality = containingDeclaration instanceof ClassDescriptor
? resolveMemberModalityFromModifiers(property, getDefaultModality(containingDeclaration, visibility, property.hasBody()),
? resolveMemberModalityFromModifiers(variableDeclaration,
getDefaultModality(containingDeclaration, visibility, propertyInfo.getHasBody()),
trace.getBindingContext(), containingDeclaration)
: Modality.FINAL;
AnnotationSplitter.PropertyWrapper wrapper = new AnnotationSplitter.PropertyWrapper(property);
AnnotationSplitter.PropertyWrapper wrapper = new AnnotationSplitter.PropertyWrapper(variableDeclaration);
Annotations allAnnotations = annotationResolver.resolveAnnotationsWithoutArguments(scopeForDeclarationResolution, modifierList, trace);
AnnotationSplitter annotationSplitter =
@@ -812,16 +878,16 @@ public class DescriptorResolver {
modality,
visibility,
isVar,
KtPsiUtil.safeName(property.getName()),
KtPsiUtil.safeName(variableDeclaration.getName()),
CallableMemberDescriptor.Kind.DECLARATION,
KotlinSourceElementKt.toSourceElement(property),
KotlinSourceElementKt.toSourceElement(variableDeclaration),
modifierList != null && modifierList.hasModifier(KtTokens.LATEINIT_KEYWORD),
modifierList != null && modifierList.hasModifier(KtTokens.CONST_KEYWORD),
modifierList != null && modifierList.hasModifier(KtTokens.HEADER_KEYWORD) ||
containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).isHeader(),
modifierList != null && modifierList.hasModifier(KtTokens.IMPL_KEYWORD),
modifierList != null && modifierList.hasModifier(KtTokens.EXTERNAL_KEYWORD),
property.hasDelegate()
propertyInfo.getHasDelegate()
);
wrapper.setDescriptor(propertyDescriptor);
@@ -831,7 +897,7 @@ public class DescriptorResolver {
KotlinType receiverType = null;
{
List<KtTypeParameter> typeParameters = property.getTypeParameters();
List<KtTypeParameter> typeParameters = variableDeclaration.getTypeParameters();
if (typeParameters.isEmpty()) {
scopeForDeclarationResolutionWithTypeParameters = scopeForDeclarationResolution;
scopeForInitializerResolutionWithTypeParameters = scopeForInitializerResolution;
@@ -853,12 +919,12 @@ public class DescriptorResolver {
}
writableScopeForDeclarationResolution.freeze();
writableScopeForInitializerResolution.freeze();
resolveGenericBounds(property, propertyDescriptor, writableScopeForDeclarationResolution, typeParameterDescriptors, trace);
resolveGenericBounds(variableDeclaration, propertyDescriptor, writableScopeForDeclarationResolution, typeParameterDescriptors, trace);
scopeForDeclarationResolutionWithTypeParameters = writableScopeForDeclarationResolution;
scopeForInitializerResolutionWithTypeParameters = writableScopeForInitializerResolution;
}
KtTypeReference receiverTypeRef = property.getReceiverTypeReference();
KtTypeReference receiverTypeRef = variableDeclaration.getReceiverTypeReference();
if (receiverTypeRef != null) {
receiverType = typeResolver.resolveType(scopeForDeclarationResolutionWithTypeParameters, receiverTypeRef, trace, true);
}
@@ -868,31 +934,45 @@ public class DescriptorResolver {
DescriptorFactory.createExtensionReceiverParameterForCallable(propertyDescriptor, receiverType);
LexicalScope scopeForInitializer = ScopeUtils.makeScopeForPropertyInitializer(scopeForInitializerResolutionWithTypeParameters, propertyDescriptor);
KotlinType typeIfKnown = variableTypeAndInitializerResolver.resolveTypeNullable(
KotlinType propertyType = propertyInfo.getVariableType();
KotlinType typeIfKnown = propertyType != null ? propertyType : variableTypeAndInitializerResolver.resolveTypeNullable(
propertyDescriptor, scopeForInitializer,
property, dataFlowInfo, /* local = */ trace, false
variableDeclaration, dataFlowInfo, /* local = */ trace, false
);
PropertyGetterDescriptorImpl getter = resolvePropertyGetterDescriptor(
scopeForDeclarationResolutionWithTypeParameters, property, propertyDescriptor, annotationSplitter, trace, typeIfKnown);
scopeForDeclarationResolutionWithTypeParameters,
variableDeclaration,
propertyDescriptor,
annotationSplitter,
trace,
typeIfKnown,
propertyInfo.getPropertyGetter(),
propertyInfo.getHasDelegate());
KotlinType type = typeIfKnown != null ? typeIfKnown : getter.getReturnType();
assert type != null : "At least getter type must be initialized via resolvePropertyGetterDescriptor";
variableTypeAndInitializerResolver.setConstantForVariableIfNeeded(
propertyDescriptor, scopeForInitializer, property, dataFlowInfo, type, trace
propertyDescriptor, scopeForInitializer, variableDeclaration, dataFlowInfo, type, trace
);
propertyDescriptor.setType(type, typeParameterDescriptors, getDispatchReceiverParameterIfNeeded(containingDeclaration),
receiverDescriptor);
PropertySetterDescriptor setter = resolvePropertySetterDescriptor(
scopeForDeclarationResolutionWithTypeParameters, property, propertyDescriptor, annotationSplitter, trace);
scopeForDeclarationResolutionWithTypeParameters,
variableDeclaration,
propertyDescriptor,
annotationSplitter,
trace,
propertyInfo.getPropertySetter(),
propertyInfo.getHasDelegate());
propertyDescriptor.initialize(getter, setter);
trace.record(BindingContext.VARIABLE, property, propertyDescriptor);
trace.record(BindingContext.VARIABLE, variableDeclaration, propertyDescriptor);
return propertyDescriptor;
}
@@ -924,12 +1004,13 @@ public class DescriptorResolver {
@Nullable
private PropertySetterDescriptor resolvePropertySetterDescriptor(
@NotNull LexicalScope scopeWithTypeParameters,
@NotNull KtProperty property,
@NotNull KtVariableDeclaration property,
@NotNull PropertyDescriptor propertyDescriptor,
@NotNull AnnotationSplitter annotationSplitter,
@NotNull BindingTrace trace
@NotNull BindingTrace trace,
@Nullable KtPropertyAccessor setter,
boolean hasDelegate
) {
KtPropertyAccessor setter = property.getSetter();
PropertySetterDescriptorImpl setterDescriptor = null;
if (setter != null) {
Annotations annotations = new CompositeAnnotations(CollectionsKt.listOf(
@@ -986,7 +1067,7 @@ public class DescriptorResolver {
}
else if (property.isVar()) {
Annotations setterAnnotations = annotationSplitter.getAnnotationsForTarget(PROPERTY_SETTER);
setterDescriptor = DescriptorFactory.createSetter(propertyDescriptor, setterAnnotations, !property.hasDelegate(),
setterDescriptor = DescriptorFactory.createSetter(propertyDescriptor, setterAnnotations, !hasDelegate,
/* isExternal = */ false, property.hasModifier(KtTokens.INLINE_KEYWORD),
propertyDescriptor.getSource());
}
@@ -1003,14 +1084,15 @@ public class DescriptorResolver {
@NotNull
private PropertyGetterDescriptorImpl resolvePropertyGetterDescriptor(
@NotNull LexicalScope scopeForDeclarationResolution,
@NotNull KtProperty property,
@NotNull KtVariableDeclaration property,
@NotNull PropertyDescriptor propertyDescriptor,
@NotNull AnnotationSplitter annotationSplitter,
@NotNull BindingTrace trace,
@Nullable KotlinType propertyTypeIfKnown
@Nullable KotlinType propertyTypeIfKnown,
@Nullable KtPropertyAccessor getter,
boolean hasDelegate
) {
PropertyGetterDescriptorImpl getterDescriptor;
KtPropertyAccessor getter = property.getGetter();
KotlinType getterType;
if (getter != null) {
Annotations getterAnnotations = new CompositeAnnotations(CollectionsKt.listOf(
@@ -1031,7 +1113,7 @@ public class DescriptorResolver {
}
else {
Annotations getterAnnotations = annotationSplitter.getAnnotationsForTarget(PROPERTY_GETTER);
getterDescriptor = DescriptorFactory.createGetter(propertyDescriptor, getterAnnotations, !property.hasDelegate(),
getterDescriptor = DescriptorFactory.createGetter(propertyDescriptor, getterAnnotations, !hasDelegate,
/* isExternal = */ false, property.hasModifier(KtTokens.INLINE_KEYWORD));
getterType = propertyTypeIfKnown;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -62,6 +62,7 @@ class LazyTopDownAnalyzer(
val properties = ArrayList<KtProperty>()
val functions = ArrayList<KtNamedFunction>()
val typeAliases = ArrayList<KtTypeAlias>()
val destructuringDeclarations = ArrayList<KtDestructuringDeclaration>()
// fill in the context
for (declaration in declarations) {
@@ -168,7 +169,9 @@ class LazyTopDownAnalyzer(
}
override fun visitDestructuringDeclaration(destructuringDeclaration: KtDestructuringDeclaration) {
// Ignore: multi-declarations are only allowed locally
if (destructuringDeclaration.containingKtFile.isScript) {
destructuringDeclarations.add(destructuringDeclaration)
}
}
override fun visitNamedFunction(function: KtNamedFunction) {
@@ -191,6 +194,8 @@ class LazyTopDownAnalyzer(
createPropertyDescriptors(c, topLevelFqNames, properties)
createPropertiesFromDestructuringDeclarations(c, topLevelFqNames, destructuringDeclarations)
createTypeAliasDescriptors(c, topLevelFqNames, typeAliases)
resolveAllHeadersInClasses(c)
@@ -258,6 +263,21 @@ class LazyTopDownAnalyzer(
}
}
private fun createPropertiesFromDestructuringDeclarations(
c: TopDownAnalysisContext,
topLevelFqNames: Multimap<FqName, KtElement>,
destructuringDeclarations: List<KtDestructuringDeclaration>) {
for (destructuringDeclaration in destructuringDeclarations) {
for (entry in destructuringDeclaration.entries) {
val descriptor = lazyDeclarationResolver.resolveToDescriptor(entry) as PropertyDescriptor
c.destructuringDeclarationEntries[entry] = descriptor
ForceResolveUtil.forceResolveAllContents(descriptor.annotations)
registerTopLevelFqName(topLevelFqNames, entry, descriptor)
}
}
}
private fun registerTopLevelFqName(topLevelFqNames: Multimap<FqName, KtElement>, declaration: KtNamedDeclaration, descriptor: DeclarationDescriptor) {
if (DescriptorUtils.isTopLevelDeclaration(descriptor)) {
val fqName = declaration.fqName
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -46,6 +46,7 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
private final Map<KtProperty, PropertyDescriptor> properties = Maps.newLinkedHashMap();
private final Map<KtParameter, PropertyDescriptor> primaryConstructorParameterProperties = Maps.newHashMap();
private final Map<KtTypeAlias, TypeAliasDescriptor> typeAliases = Maps.newLinkedHashMap();
private final Map<KtDestructuringDeclarationEntry, PropertyDescriptor> destructuringDeclarationEntries = Maps.newLinkedHashMap();
private Map<KtCallableDeclaration, CallableMemberDescriptor> members = null;
private final Map<KtScript, LazyScriptDescriptor> scripts = Maps.newLinkedHashMap();
@@ -145,6 +146,11 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
return typeAliases;
}
@Override
public Map<KtDestructuringDeclarationEntry, PropertyDescriptor> getDestructuringDeclarationEntries() {
return destructuringDeclarationEntries;
}
@NotNull
public Map<KtCallableDeclaration, CallableMemberDescriptor> getMembers() {
if (members == null) {
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2017 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.kotlin.resolve
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPropertyAccessor
import org.jetbrains.kotlin.types.KotlinType
class VariableAsPropertyInfo(
val propertyGetter: KtPropertyAccessor?,
val propertySetter: KtPropertyAccessor?,
val variableType: KotlinType?,
val hasBody: Boolean,
val hasDelegate: Boolean
) {
companion object {
fun createFromDestructuringDeclarationEntry(type: KotlinType): VariableAsPropertyInfo {
return VariableAsPropertyInfo(null, null, type, false, false)
}
fun createFromProperty(property: KtProperty): VariableAsPropertyInfo {
return VariableAsPropertyInfo(property.getter, property.setter, null, property.hasBody(), property.hasDelegate())
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -224,6 +224,17 @@ public class LazyDeclarationResolver {
return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, property);
}
@Override
public DeclarationDescriptor visitDestructuringDeclarationEntry(
@NotNull KtDestructuringDeclarationEntry destructuringDeclarationEntry, Void data
) {
LookupLocation location = lookupLocationFor(destructuringDeclarationEntry, false);
KtDestructuringDeclaration destructuringDeclaration = ((KtDestructuringDeclaration) destructuringDeclarationEntry.getParent());
MemberScope scopeForDeclaration = getMemberScopeDeclaredIn(destructuringDeclaration, location);
scopeForDeclaration.getContributedVariables(destructuringDeclarationEntry.getNameAsSafeName(), location);
return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, destructuringDeclarationEntry);
}
@Override
public DeclarationDescriptor visitTypeAlias(@NotNull KtTypeAlias typeAlias, Void data) {
LookupLocation location = lookupLocationFor(typeAlias, typeAlias.isTopLevel());
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -37,6 +37,7 @@ abstract class AbstractPsiBasedDeclarationProvider(storageManager: StorageManage
val properties = ArrayListMultimap.create<Name, KtProperty>()
val classesAndObjects = ArrayListMultimap.create<Name, KtClassLikeInfo>() // order matters here
val typeAliases = ArrayListMultimap.create<Name, KtTypeAlias>()
val destructuringDeclarationsEntries = ArrayListMultimap.create<Name, KtDestructuringDeclarationEntry>()
fun putToIndex(declaration: KtDeclaration) {
if (declaration is KtAnonymousInitializer || declaration is KtSecondaryConstructor) return
@@ -55,7 +56,12 @@ abstract class AbstractPsiBasedDeclarationProvider(storageManager: StorageManage
val scriptInfo = KtScriptInfo(declaration)
classesAndObjects.put(scriptInfo.script.nameAsName, scriptInfo)
}
is KtParameter, is KtDestructuringDeclaration -> {
is KtDestructuringDeclaration -> {
for (entry in declaration.entries) {
destructuringDeclarationsEntries.put(safeNameForLazyResolve(entry.nameAsName), entry)
}
}
is KtParameter -> {
// Do nothing, just put it into allDeclarations is enough
}
else -> throw IllegalArgumentException("Unknown declaration: " + declaration)
@@ -80,6 +86,9 @@ abstract class AbstractPsiBasedDeclarationProvider(storageManager: StorageManage
override fun getPropertyDeclarations(name: Name): List<KtProperty>
= index().properties[ResolveSessionUtils.safeNameForLazyResolve(name)].toList()
override fun getDestructuringDeclarationsEntries(name: Name): Collection<KtDestructuringDeclarationEntry>
= index().destructuringDeclarationsEntries[ResolveSessionUtils.safeNameForLazyResolve(name)].toList()
override fun getClassOrObjectDeclarations(name: Name): Collection<KtClassLikeInfo>
= index().classesAndObjects[ResolveSessionUtils.safeNameForLazyResolve(name)]
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.resolve.lazy.declarations
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
class CombinedPackageMemberDeclarationProvider(val providers: Collection<PackageMemberDeclarationProvider>) : PackageMemberDeclarationProvider {
@@ -31,6 +32,10 @@ class CombinedPackageMemberDeclarationProvider(val providers: Collection<Package
override fun getPropertyDeclarations(name: Name) = providers.flatMap { it.getPropertyDeclarations(name) }
override fun getDestructuringDeclarationsEntries(name: Name): Collection<KtDestructuringDeclarationEntry> {
return providers.flatMap { it.getDestructuringDeclarationsEntries(name) }
}
override fun getClassOrObjectDeclarations(name: Name) = providers.flatMap { it.getClassOrObjectDeclarations(name) }
override fun getTypeAliasDeclarations(name: Name) = providers.flatMap { it.getTypeAliasDeclarations(name) }
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -16,12 +16,9 @@
package org.jetbrains.kotlin.resolve.lazy.declarations
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtTypeAlias
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
interface DeclarationProvider {
@@ -31,6 +28,8 @@ interface DeclarationProvider {
fun getPropertyDeclarations(name: Name): Collection<KtProperty>
fun getDestructuringDeclarationsEntries(name: Name): Collection<KtDestructuringDeclarationEntry>
fun getClassOrObjectDeclarations(name: Name): Collection<KtClassLikeInfo>
fun getTypeAliasDeclarations(name: Name): Collection<KtTypeAlias>
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -128,6 +128,17 @@ protected constructor(
result.add(propertyDescriptor)
}
for (entry in declarationProvider.getDestructuringDeclarationsEntries(name)) {
val propertyDescriptor = c.descriptorResolver.resolveDestructuringDeclarationEntryAsProperty(
thisDescriptor,
getScopeForMemberDeclarationResolution(entry),
getScopeForInitializerResolution(entry),
entry,
trace,
c.declarationScopeProvider.getOuterDataFlowInfoForDeclaration(entry))
result.add(propertyDescriptor)
}
getNonDeclaredProperties(name, result)
return result.toList()
@@ -49,9 +49,7 @@ class DestructuringDeclarationResolver(
): List<VariableDescriptor> {
val result = arrayListOf<VariableDescriptor>()
for ((componentIndex, entry) in destructuringDeclaration.entries.withIndex()) {
val componentName = DataClassDescriptorResolver.createComponentName(componentIndex + 1)
val componentType = resolveComponentFunctionAndGetType(componentName, context, entry, receiver, initializer)
val componentType = resolveInitializer(entry, receiver, initializer, context, componentIndex)
val variableDescriptor = localVariableResolver.resolveLocalVariableDescriptorWithType(scope, entry, componentType, context.trace)
result.add(variableDescriptor)
@@ -73,6 +71,17 @@ class DestructuringDeclarationResolver(
writableScope.addVariableDescriptor(it)
}
fun resolveInitializer(
entry: KtDestructuringDeclarationEntry,
receiver: ReceiverValue?,
initializer: KtExpression?,
context: ExpressionTypingContext,
componentIndex: Int
): KotlinType {
val componentName = DataClassDescriptorResolver.createComponentName(componentIndex + 1)
return resolveComponentFunctionAndGetType(componentName, context, entry, receiver, initializer)
}
private fun resolveComponentFunctionAndGetType(
componentName: Name,
context: ExpressionTypingContext,
@@ -0,0 +1,16 @@
val (a1, a2) = A()
val (b1: Int, b2: Int) = <!COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH!>A()<!>
val (c1) = <!UNRESOLVED_REFERENCE!>unresolved<!>
<!WRONG_MODIFIER_TARGET!>private<!> val (d1) = A()
val (e1, _) = A()
a1
a2
e1
class A {
operator fun component1() = 1
operator fun component2() = ""
}
@@ -0,0 +1,18 @@
package
public final class DestructuringDeclarationsScript : kotlin.script.templates.standard.ScriptTemplateWithArgs {
public constructor DestructuringDeclarationsScript(/*0*/ args: kotlin.Array<kotlin.String>)
public final override /*1*/ /*fake_override*/ val args: kotlin.Array<kotlin.String>
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final class A {
public constructor A()
public final operator fun component1(): kotlin.Int
public final operator fun component2(): kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -0,0 +1,7 @@
val (a, b, c) = A(<!NO_VALUE_FOR_PARAMETER!>)<!>
class A(val a: Int) {
operator fun component1() {}
operator fun component2() {}
operator fun component3() {}
}
@@ -0,0 +1,20 @@
package
public final class ResolveInitializerOfDestructuringDeclarationOnce : kotlin.script.templates.standard.ScriptTemplateWithArgs {
public constructor ResolveInitializerOfDestructuringDeclarationOnce(/*0*/ args: kotlin.Array<kotlin.String>)
public final override /*1*/ /*fake_override*/ val args: kotlin.Array<kotlin.String>
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final class A {
public constructor A(/*0*/ a: kotlin.Int)
public final val a: kotlin.Int
public final operator fun component1(): kotlin.Unit
public final operator fun component2(): kotlin.Unit
public final operator fun component3(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -23576,6 +23576,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("destructuringDeclarationsScript.kts")
public void testDestructuringDeclarationsScript() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/script/destructuringDeclarationsScript.kts");
doTest(fileName);
}
@TestMetadata("imports.kts")
public void testImports() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/script/imports.kts");
@@ -23588,6 +23594,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("resolveInitializerOfDestructuringDeclarationOnce.kts")
public void testResolveInitializerOfDestructuringDeclarationOnce() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/script/resolveInitializerOfDestructuringDeclarationOnce.kts");
doTest(fileName);
}
@TestMetadata("SimpleScript.kts")
public void testSimpleScript() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/script/SimpleScript.kts");
@@ -617,6 +617,8 @@ class ResolveElementCache(
override fun getTypeAliases(): MutableMap<KtTypeAlias, TypeAliasDescriptor> = hashMapOf()
override fun getDestructuringDeclarationEntries(): MutableMap<KtDestructuringDeclarationEntry, PropertyDescriptor> = hashMapOf()
override fun getDeclaringScope(declaration: KtDeclaration): LexicalScope? = declaringScopes(declaration)
override fun getScripts(): MutableMap<KtScript, LazyScriptDescriptor> = hashMapOf()
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -85,6 +85,10 @@ class StubBasedPackageMemberDeclarationProvider(
}
}
override fun getDestructuringDeclarationsEntries(name: Name): Collection<KtDestructuringDeclarationEntry> {
return emptyList()
}
override fun getAllDeclaredSubPackages(nameFilter: (Name) -> Boolean): Collection<FqName> {
return PackageIndexUtil.getSubPackageFqNames(fqName, searchScope, project, nameFilter)
}