From 9a435e332f7478ad5e569482320ede65393891cb Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Wed, 26 Aug 2015 22:13:41 +0300 Subject: [PATCH] Fix InnerClassesScopeWrapper - remove properties and functions from this scope. --- .../diagnostics/tests/RecursiveResolve.kt | 4 +- .../diagnostics/tests/RecursiveResolve.txt | 4 +- .../tests/objects/objectInsideFun.kt | 11 +++++ .../tests/objects/objectInsideFun.txt | 11 +++++ .../regressions/objectInsideFun.resolve | 9 ++++ .../checkers/JetDiagnosticsTestGenerated.java | 6 +++ .../kotlin/resolve/ResolveTestGenerated.java | 6 +++ .../scopes/InnerClassesScopeWrapper.kt | 21 ++++++---- .../jetbrains/kotlin/idea/util/scopeUtils.kt | 42 +++++++++++++++++++ .../smart/MultipleArgumentsItemProvider.kt | 7 ++-- .../JetChangeSignatureUsageProcessor.java | 8 ++-- 11 files changed, 110 insertions(+), 19 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/objects/objectInsideFun.kt create mode 100644 compiler/testData/diagnostics/tests/objects/objectInsideFun.txt create mode 100644 compiler/testData/resolve/regressions/objectInsideFun.resolve create mode 100644 idea/ide-common/src/org/jetbrains/kotlin/idea/util/scopeUtils.kt diff --git a/compiler/testData/diagnostics/tests/RecursiveResolve.kt b/compiler/testData/diagnostics/tests/RecursiveResolve.kt index e8a9c181957..55e44344ff8 100644 --- a/compiler/testData/diagnostics/tests/RecursiveResolve.kt +++ b/compiler/testData/diagnostics/tests/RecursiveResolve.kt @@ -32,7 +32,7 @@ class Test2(foo: Any?, bar: Any?) { class Test3(foo: Any?, bar: Any?) { val foo = foo ?: this private val bar = bar ?: this - private val bas = bas() + private val bas = bas() val bas2 = bas2() private fun bas(): Int = null!! @@ -47,7 +47,7 @@ class Test3(foo: Any?, bar: Any?) { class Test4(foo: Any?, bar: Any?) { val foo = foo ?: this private val bar = bar ?: this - private val bas = bas() + private val bas = bas() val bas2 = bas2() private fun bas(): Int = null!! diff --git a/compiler/testData/diagnostics/tests/RecursiveResolve.txt b/compiler/testData/diagnostics/tests/RecursiveResolve.txt index 5724383da44..d51f19ddeb3 100644 --- a/compiler/testData/diagnostics/tests/RecursiveResolve.txt +++ b/compiler/testData/diagnostics/tests/RecursiveResolve.txt @@ -37,7 +37,7 @@ internal final class Test2 { internal final class Test3 { public constructor Test3(/*0*/ foo: kotlin.Any?, /*1*/ bar: kotlin.Any?) private final val bar: kotlin.Any - private final val bas: [ERROR : Type for bas()] + private final val bas: kotlin.Int internal final val bas2: kotlin.Int internal final val foo: kotlin.Any internal final fun bar(): kotlin.Int @@ -54,7 +54,7 @@ internal final class Test3 { internal final class Test4 { public constructor Test4(/*0*/ foo: kotlin.Any?, /*1*/ bar: kotlin.Any?) private final val bar: kotlin.Any - private final val bas: [ERROR : Type for bas()] + private final val bas: kotlin.Int internal final val bas2: kotlin.Int internal final val foo: kotlin.Any internal final fun bar(): kotlin.Int diff --git a/compiler/testData/diagnostics/tests/objects/objectInsideFun.kt b/compiler/testData/diagnostics/tests/objects/objectInsideFun.kt new file mode 100644 index 00000000000..481c7c017ac --- /dev/null +++ b/compiler/testData/diagnostics/tests/objects/objectInsideFun.kt @@ -0,0 +1,11 @@ +interface A { + val foo: Int + val bar: String + get() = "" +} + +fun test(foo: Int, bar: Int) { + object : A { + override val foo: Int = foo + bar + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/objects/objectInsideFun.txt b/compiler/testData/diagnostics/tests/objects/objectInsideFun.txt new file mode 100644 index 00000000000..61f1b2c168a --- /dev/null +++ b/compiler/testData/diagnostics/tests/objects/objectInsideFun.txt @@ -0,0 +1,11 @@ +package + +internal fun test(/*0*/ foo: kotlin.Int, /*1*/ bar: kotlin.Int): kotlin.Unit + +internal interface A { + internal open val bar: kotlin.String + internal abstract val foo: kotlin.Int + 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 +} diff --git a/compiler/testData/resolve/regressions/objectInsideFun.resolve b/compiler/testData/resolve/regressions/objectInsideFun.resolve new file mode 100644 index 00000000000..f8cf8f16802 --- /dev/null +++ b/compiler/testData/resolve/regressions/objectInsideFun.resolve @@ -0,0 +1,9 @@ +interface A { + ~from-interface~val foo: Int +} + +fun test(~param~foo: Int) { + object : A { + ~property~override val foo: Int = `param`foo + } +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 758cd33d0be..c7462ea43f9 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -9465,6 +9465,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("objectInsideFun.kt") + public void testObjectInsideFun() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/objects/objectInsideFun.kt"); + doTest(fileName); + } + @TestMetadata("objectLiteralExpressionTypeMismatch.kt") public void testObjectLiteralExpressionTypeMismatch() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/objects/objectLiteralExpressionTypeMismatch.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/resolve/ResolveTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/resolve/ResolveTestGenerated.java index 94fbbb13c03..53747ee2f25 100644 --- a/compiler/tests/org/jetbrains/kotlin/resolve/ResolveTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/resolve/ResolveTestGenerated.java @@ -480,6 +480,12 @@ public class ResolveTestGenerated extends AbstractResolveTest { String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolve/regressions/kt300.resolve"); doTest(fileName); } + + @TestMetadata("objectInsideFun.resolve") + public void testObjectInsideFun() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolve/regressions/objectInsideFun.resolve"); + doTest(fileName); + } } @TestMetadata("compiler/testData/resolve/varargs") diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/InnerClassesScopeWrapper.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/InnerClassesScopeWrapper.kt index 2947f6539d8..ca4656c7e0c 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/InnerClassesScopeWrapper.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/InnerClassesScopeWrapper.kt @@ -17,22 +17,27 @@ package org.jetbrains.kotlin.resolve.scopes import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.Printer + +public class InnerClassesScopeWrapper(val workerScope: JetScope) : JetScopeImpl() { + override fun getContainingDeclaration(): DeclarationDescriptor { + return workerScope.getContainingDeclaration() + } -public class InnerClassesScopeWrapper(override val workerScope: JetScope) : AbstractScopeAdapter() { override fun getClassifier(name: Name, location: LookupLocation) = workerScope.getClassifier(name, location) as? ClassDescriptor - override fun getDeclarationsByLabel(labelName: Name) = workerScope.getDeclarationsByLabel(labelName).filterIsInstance() - - override fun getDescriptors(kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean): List { + override fun getDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): List { val restrictedFilter = kindFilter.restrictedToKindsOrNull(DescriptorKindFilter.CLASSIFIERS_MASK) ?: return listOf() return workerScope.getDescriptors(restrictedFilter, nameFilter).filterIsInstance() } - override fun getImplicitReceiversHierarchy(): List = listOf() + override fun printScopeStructure(p: Printer) { + p.println("InnerClassesScopeWrapper for scope:") + workerScope.printScopeStructure(p) + } - override fun toString() = "Classes from " + workerScope + override fun toString() = "Classes from $workerScope" } diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/scopeUtils.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/scopeUtils.kt new file mode 100644 index 00000000000..4644fa6953a --- /dev/null +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/scopeUtils.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2015 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.idea.util + +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.VariableDescriptor +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.scopes.JetScope + + +public fun JetScope.getAllAccessibleVariables(name: Name): Collection + = getVariablesFromImplicitReceivers(name) + getProperties(name, NoLookupLocation.FROM_IDE) + listOfNotNull(getLocalVariable(name)) + +public fun JetScope.getAllAccessibleFunctions(name: Name): Collection + = getImplicitReceiversWithInstance().flatMap { it.type.memberScope.getFunctions(name, NoLookupLocation.FROM_IDE) } + + getFunctions(name, NoLookupLocation.FROM_IDE) + +public fun JetScope.getVariablesFromImplicitReceivers(name: Name): Collection = getImplicitReceiversWithInstance().flatMap { + it.type.memberScope.getProperties(name, NoLookupLocation.FROM_IDE) +} + +public fun JetScope.getVariableFromImplicitReceivers(name: Name): VariableDescriptor? { + getImplicitReceiversWithInstance().forEach { + it.type.memberScope.getProperties(name, NoLookupLocation.FROM_IDE).singleOrNull()?.let { return it } + } + return null +} \ No newline at end of file diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/MultipleArgumentsItemProvider.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/MultipleArgumentsItemProvider.kt index 9b0b5c5109f..67ee38d6463 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/MultipleArgumentsItemProvider.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/MultipleArgumentsItemProvider.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.idea.JetDescriptorIconProvider import org.jetbrains.kotlin.idea.completion.* +import org.jetbrains.kotlin.idea.util.getVariableFromImplicitReceivers import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.psi.JetExpression import org.jetbrains.kotlin.renderer.render @@ -31,8 +32,7 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue import org.jetbrains.kotlin.resolve.scopes.JetScope import org.jetbrains.kotlin.types.checker.JetTypeChecker -import java.util.ArrayList -import java.util.HashSet +import java.util.* class MultipleArgumentsItemProvider(val bindingContext: BindingContext, val smartCastCalculator: SmartCastCalculator) { @@ -90,7 +90,8 @@ class MultipleArgumentsItemProvider(val bindingContext: BindingContext, private fun variableInScope(parameter: ValueParameterDescriptor, scope: JetScope): VariableDescriptor? { val name = parameter.getName() //TODO: there can be more than one property with such name in scope and we should be able to select one (but we need API for this) - val variable = scope.getLocalVariable(name) ?: scope.getProperties(name, NoLookupLocation.FROM_IDE).singleOrNull() ?: return null + val variable = scope.getLocalVariable(name) ?: scope.getProperties(name, NoLookupLocation.FROM_IDE).singleOrNull() ?: + scope.getVariableFromImplicitReceivers(name) ?: return null return if (smartCastCalculator.types(variable).any { JetTypeChecker.DEFAULT.isSubtypeOf(it, parameter.getType()) }) variable else diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java index d2ea6387006..6f9a499ab3e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java @@ -57,7 +57,7 @@ import org.jetbrains.kotlin.idea.references.JetSimpleNameReference; import org.jetbrains.kotlin.idea.references.ReferencesPackage; import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchPackage; import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers; -import org.jetbrains.kotlin.incremental.components.NoLookupLocation; +import org.jetbrains.kotlin.idea.util.UtilPackage; import org.jetbrains.kotlin.kdoc.psi.impl.KDocName; import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor; import org.jetbrains.kotlin.name.Name; @@ -619,8 +619,8 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro if (!kind.getIsConstructor() && callableScope != null && !info.getNewName().isEmpty()) { Name newName = Name.identifier(info.getNewName()); Collection conflicts = oldDescriptor instanceof FunctionDescriptor - ? callableScope.getFunctions(newName, NoLookupLocation.FROM_IDE) - : callableScope.getProperties(newName, NoLookupLocation.FROM_IDE); + ? UtilPackage.getAllAccessibleFunctions(callableScope, newName) + : UtilPackage.getAllAccessibleVariables(callableScope, newName); for (CallableDescriptor conflict : conflicts) { if (conflict == oldDescriptor) continue; @@ -643,7 +643,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro } if (parametersScope != null) { if (kind == JetMethodDescriptor.Kind.PRIMARY_CONSTRUCTOR && valOrVar != JetValVar.None) { - for (VariableDescriptor property : parametersScope.getProperties(Name.identifier(parameterName), NoLookupLocation.FROM_IDE)) { + for (VariableDescriptor property : UtilPackage.getVariablesFromImplicitReceivers(parametersScope, Name.identifier(parameterName))) { PsiElement propertyDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(property); if (propertyDeclaration != null && !(propertyDeclaration.getParent() instanceof JetParameterList)) {