From 450168d6c72755eece72c2257832f6e3ff8bbc9c Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Tue, 19 May 2015 14:17:39 +0300 Subject: [PATCH] DeprecatedSymbolUsageFix - code refactoring --- .../org/jetbrains/kotlin/idea/core/Utils.kt | 26 +- .../idea/quickfix/DeprecatedSymbolUsageFix.kt | 237 +----------------- .../quickfix/ReplaceWithAnnotationAnalyzer.kt | 199 +++++++++++++++ 3 files changed, 235 insertions(+), 227 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceWithAnnotationAnalyzer.kt diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt index 131eacb3d6c..b2d4ed01dea 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt @@ -16,11 +16,13 @@ package org.jetbrains.kotlin.idea.core +import com.intellij.openapi.util.Key +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiRecursiveElementVisitor import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor -import org.jetbrains.kotlin.psi.Call -import org.jetbrains.kotlin.psi.FunctionLiteralArgument -import org.jetbrains.kotlin.psi.ValueArgument +import org.jetbrains.kotlin.psi.* +import java.util.ArrayList import java.util.HashMap public fun Call.mapArgumentsToParameters(targetDescriptor: CallableDescriptor): Map { @@ -63,3 +65,21 @@ public fun Call.mapArgumentsToParameters(targetDescriptor: CallableDescriptor): return map } + +// TODO: it can be default value for parameter but it's not supported yet by the compiler +public inline fun PsiElement.collectElementsOfType(): Collection { + return collectElementsOfType { true } +} + +public inline fun PsiElement.collectElementsOfType(@inlineOptions(InlineOption.ONLY_LOCAL_RETURN) predicate: (TElement) -> Boolean): Collection { + val result = ArrayList() + this.accept(object : PsiRecursiveElementVisitor(){ + override fun visitElement(element: PsiElement) { + if (element is TElement && predicate(element)) { + result.add(element) + } + super.visitElement(element) + } + }) + return result +} diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFix.kt index 20590d818a5..0f7eef1a723 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFix.kt @@ -24,24 +24,21 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.PsiRecursiveElementVisitor import org.jetbrains.kotlin.analyzer.analyzeInContext -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Errors -import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade +import org.jetbrains.kotlin.idea.core.collectElementsOfType import org.jetbrains.kotlin.idea.core.refactoring.JetNameSuggester import org.jetbrains.kotlin.idea.core.refactoring.JetNameValidator -import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport -import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.intentions.setType import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.ImportInsertHelper import org.jetbrains.kotlin.idea.util.ShortenReferences import org.jetbrains.kotlin.lexer.JetTokens -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression @@ -49,34 +46,23 @@ import org.jetbrains.kotlin.psi.psiUtil.isAncestor import org.jetbrains.kotlin.psi.psiUtil.replaced import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.FunctionDescriptorUtil import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns -import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension -import org.jetbrains.kotlin.resolve.scopes.* -import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.JetType -import org.jetbrains.kotlin.utils.Printer -import org.jetbrains.kotlin.utils.addIfNotNull -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import java.util.ArrayList -import java.util.LinkedHashSet //TODO: replacement of class usages //TODO: different replacements for property accessors //TODO: replace all in project quickfixes on usage and on deprecated annotation public class DeprecatedSymbolUsageFix( element: JetSimpleNameExpression/*TODO?*/, - val replaceWith: DeprecatedSymbolUsageFix.ReplaceWith + val replaceWith: ReplaceWith ) : JetIntentionAction(element) { - //TODO: use ReplaceWith from package kotlin - private data class ReplaceWith(val expression: String, vararg val imports: String) - override fun getFamilyName() = "Replace deprecated symbol usage" override fun getText() = "Replace with '${replaceWith.expression}'" //TODO: substitute? @@ -116,11 +102,12 @@ public class DeprecatedSymbolUsageFix( explicitReceiver?.putCopyableUserData(FROM_THIS_KEY, Unit) //TODO: infix and operator calls - var (expression, imports, parameterUsages) = replaceWith.toExpression(descriptor.getOriginal(), element.getResolutionFacade(), file, project) + var (expression, imports, parameterUsages) = ReplaceWithAnnotationAnalyzer.analyze( + replaceWith, descriptor.getOriginal(), element.getResolutionFacade(), file, project) //TODO: implicit receiver is not always "this" //TODO: this@ - for (thisExpression in expression.collectThisExpressions()) { + for (thisExpression in expression.collectElementsOfType()) { if (explicitReceiver != null) { thisExpression.replace(explicitReceiver) } @@ -165,7 +152,7 @@ public class DeprecatedSymbolUsageFix( } if (expressionToReplace.isUsedAsExpression(bindingContext)) { - val thisReplaced = expression.collectExpressionsWithData(FROM_THIS_KEY, Unit) + val thisReplaced = expression.collectElementsOfType { it.getCopyableUserData(FROM_THIS_KEY) != null } expression = expression.introduceValue(explicitReceiver!!, expressionToReplace, bindingContext, thisReplaced, safeCall = true) } else { @@ -176,14 +163,14 @@ public class DeprecatedSymbolUsageFix( } if (explicitReceiver != null && explicitReceiver.shouldIntroduceVariableIfUsedTwice()) { - val thisReplaced = expression.collectExpressionsWithData(FROM_THIS_KEY, Unit) + val thisReplaced = expression.collectElementsOfType { it.getCopyableUserData(FROM_THIS_KEY) != null } if (thisReplaced.size() > 1) { expression = expression.introduceValue(explicitReceiver, expressionToReplace, bindingContext, thisReplaced) } } for ((parameter, value) in introduceValuesForParameters) { - val usagesReplaced = expression.collectExpressionsWithData(FROM_PARAMETER_KEY, parameter) + val usagesReplaced = expression.collectElementsOfType { it.getCopyableUserData(FROM_PARAMETER_KEY) == parameter } assert(usagesReplaced.size() > 1) expression = expression.introduceValue(value, expressionToReplace, bindingContext, usagesReplaced, nameSuggestion = parameter.getName().asString()) } @@ -225,128 +212,6 @@ public class DeprecatedSymbolUsageFix( editor?.moveCaret(offset) } - private data class ReplacementExpression( - val expression: JetExpression, - val imports: Collection, - val parameterUsages: Map> - ) - - private fun ReplaceWith.toExpression( - symbolDescriptor: CallableDescriptor, - resolutionFacade: ResolutionFacade, - file: JetFile/*TODO: drop it*/, - project: Project - ): ReplacementExpression { - val psiFactory = JetPsiFactory(project) - var expression = psiFactory.createExpression(expression) - - val importFqNames = imports - .filter { FqNameUnsafe.isValid(it) } - .map { FqNameUnsafe(it) } - .filter { it.isSafe() } - .mapTo(LinkedHashSet()) { it.toSafe() } - - val symbolScope = getResolutionScope(symbolDescriptor) - val explicitlyImportedSymbols = importFqNames.flatMap { resolutionFacade.resolveImportReference(file, it) } - val scope = ChainedScope(symbolDescriptor, "ReplaceWith resolution scope", ExplicitImportsScope(explicitlyImportedSymbols), symbolScope) - - val bindingContext = expression.analyzeInContext(scope) - - val thisType = symbolDescriptor.getExtensionReceiverParameter()?.getType() - ?: (symbolDescriptor.getContainingDeclaration() as? ClassifierDescriptor)?.getDefaultType() - - val receiversToAdd = ArrayList>() - - val parameterUsageKey = Key("parameterUsageKey") - - expression.accept(object : JetVisitorVoid(){ - override fun visitSimpleNameExpression(expression: JetSimpleNameExpression) { - val target = bindingContext[BindingContext.REFERENCE_TARGET, expression] ?: return - - if (target.canBeReferencedViaImport()) { - if (target.isExtension || expression.getReceiverExpression() == null) { - importFqNames.addIfNotNull(target.importableFqName) - } - } - - if (expression.getReceiverExpression() == null) { - if (target is ValueParameterDescriptor && target.getContainingDeclaration() == symbolDescriptor) { - expression.putCopyableUserData(parameterUsageKey, target) - } - - val resolvedCall = expression.getResolvedCall(bindingContext) - if (resolvedCall != null && resolvedCall.getStatus().isSuccess()) { - val receiver = if (resolvedCall.getResultingDescriptor().isExtension) - resolvedCall.getExtensionReceiver() - else - resolvedCall.getDispatchReceiver() - if (receiver is ThisReceiver) { - if (receiver.getType() == thisType) { - receiversToAdd.add(expression to "this") - } - else { - val descriptor = receiver.getDeclarationDescriptor() - if (descriptor is ClassDescriptor && descriptor.isCompanionObject()) { - receiversToAdd.add(expression to IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(descriptor)) - } - } - } - } - } - } - - override fun visitJetElement(element: JetElement) { - element.acceptChildren(this) - } - }) - - for ((expr, receiverText) in receiversToAdd) { - val expressionToReplace = expr.getParent() as? JetCallExpression ?: expr - val newExpr = expressionToReplace.replaced(psiFactory.createExpressionByPattern("$receiverText.$0", expressionToReplace)) - if (expressionToReplace == expression) { - expression = newExpr - } - } - - val parameterUsages = symbolDescriptor.getValueParameters() - .map { it to expression.collectExpressionsWithData(parameterUsageKey, it) } - .toMap() - - expression.accept(object : PsiRecursiveElementVisitor() { - override fun visitElement(element: PsiElement) { - element.putCopyableUserData(parameterUsageKey, null) - } - }) - - return ReplacementExpression(expression, importFqNames, parameterUsages) - } - - private fun getResolutionScope(descriptor: DeclarationDescriptor): JetScope { - when (descriptor) { - is PackageFragmentDescriptor -> { - val moduleDescriptor = descriptor.getContainingDeclaration() - return getResolutionScope(moduleDescriptor.getPackage(descriptor.fqName)!!) - } - - is PackageViewDescriptor -> - return descriptor.getMemberScope() - - is ClassDescriptorWithResolutionScopes -> - return descriptor.getScopeForMemberDeclarationResolution() - - is FunctionDescriptor -> - return FunctionDescriptorUtil.getFunctionInnerScope(getResolutionScope(descriptor.getContainingDeclaration()), - descriptor, RedeclarationHandler.DO_NOTHING) - - is PropertyDescriptor -> - return JetScopeUtils.getPropertyDeclarationInnerScope(descriptor, - getResolutionScope(descriptor.getContainingDeclaration()!!), - RedeclarationHandler.DO_NOTHING) - - else -> throw IllegalArgumentException("Cannot find resolution scope for $descriptor") - } - } - private fun JetExpression.introduceValue( value: JetExpression, insertDeclarationsBefore: JetExpression, @@ -429,56 +294,8 @@ public class DeprecatedSymbolUsageFix( } } - private fun JetExpression.collectExpressionsWithData(key: Key, value: T): Collection { - val result = ArrayList() - this.accept(object : JetVisitorVoid(){ - override fun visitExpression(expression: JetExpression) { - if (expression.getCopyableUserData(key) == value) { - result.add(expression) - } - else { - super.visitExpression(expression) - } - } - - override fun visitJetElement(element: JetElement) { - element.acceptChildren(this) - } - }) - return result - } - - private fun JetExpression.collectThisExpressions(): Collection { - val result = ArrayList() - this.accept(object : JetVisitorVoid(){ - override fun visitThisExpression(expression: JetThisExpression) { - if (expression.getLabelName() == null) { - result.add(expression) - } - } - - override fun visitJetElement(element: JetElement) { - element.acceptChildren(this) - } - }) - return result - } - - private fun collectNameUsages(scope: JetExpression, name: String): ArrayList { - val result = ArrayList() - scope.accept(object : JetVisitorVoid(){ - override fun visitSimpleNameExpression(expression: JetSimpleNameExpression) { - if (expression.getReceiverExpression() == null && expression.getReferencedName() == name) { - result.add(expression) - } - } - - override fun visitJetElement(element: JetElement) { - element.acceptChildren(this) - } - }) - return result - } + private fun collectNameUsages(scope: JetExpression, name: String) + = scope.collectElementsOfType { it.getReceiverExpression() == null && it.getReferencedName() == name } private fun JetExpression?.shouldIntroduceVariableIfUsedTwice(): Boolean { return when (this) { @@ -516,32 +333,4 @@ public class DeprecatedSymbolUsageFix( return ReplaceWith(pattern, *imports.toTypedArray()) } } - - private class ExplicitImportsScope(val descriptors: Collection) : JetScope { - override fun getClassifier(name: Name) = descriptors.filter { it.getName() == name }.firstIsInstanceOrNull() - - override fun getPackage(name: Name)= descriptors.filter { it.getName() == name }.firstIsInstanceOrNull() - - override fun getProperties(name: Name) = descriptors.filter { it.getName() == name }.filterIsInstance() - - override fun getLocalVariable(name: Name): VariableDescriptor? = null - - override fun getFunctions(name: Name) = descriptors.filter { it.getName() == name }.filterIsInstance() - - override fun getContainingDeclaration(): DeclarationDescriptor { - throw UnsupportedOperationException() - } - - override fun getDeclarationsByLabel(labelName: Name): Collection = emptyList() - - override fun getDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) = descriptors - - override fun getImplicitReceiversHierarchy(): List = emptyList() - - override fun getOwnDeclaredDescriptors(): Collection = emptyList() - - override fun printScopeStructure(p: Printer) { - p.println(javaClass.getName()) - } - } -} \ No newline at end of file +} diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceWithAnnotationAnalyzer.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceWithAnnotationAnalyzer.kt new file mode 100644 index 00000000000..8c50a560578 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceWithAnnotationAnalyzer.kt @@ -0,0 +1,199 @@ +/* + * 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.quickfix + +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiRecursiveElementVisitor +import org.jetbrains.kotlin.analyzer.analyzeInContext +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade +import org.jetbrains.kotlin.idea.core.collectElementsOfType +import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport +import org.jetbrains.kotlin.idea.imports.importableFqName +import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.FqNameUnsafe +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression +import org.jetbrains.kotlin.psi.psiUtil.replaced +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.FunctionDescriptorUtil +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension +import org.jetbrains.kotlin.resolve.scopes.* +import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver +import org.jetbrains.kotlin.utils.Printer +import org.jetbrains.kotlin.utils.addIfNotNull +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull +import java.util.* + +//TODO: use ReplaceWith from package kotlin +data class ReplaceWith(val expression: String, vararg val imports: String) + +object ReplaceWithAnnotationAnalyzer { + public data class ReplacementExpression( + val expression: JetExpression, + val imports: Collection, + val parameterUsages: Map> + ) + + public fun analyze( + annotation: ReplaceWith, + symbolDescriptor: CallableDescriptor, + resolutionFacade: ResolutionFacade, + file: JetFile/*TODO: drop it*/, + project: Project + ): ReplacementExpression { + val psiFactory = JetPsiFactory(project) + var expression = psiFactory.createExpression(annotation.expression) + + val importFqNames = annotation.imports + .filter { FqNameUnsafe.isValid(it) } + .map { FqNameUnsafe(it) } + .filter { it.isSafe() } + .mapTo(LinkedHashSet()) { it.toSafe() } + + val symbolScope = getResolutionScope(symbolDescriptor) + val explicitlyImportedSymbols = importFqNames.flatMap { resolutionFacade.resolveImportReference(file, it) } + val scope = ChainedScope(symbolDescriptor, "ReplaceWith resolution scope", ExplicitImportsScope(explicitlyImportedSymbols), symbolScope) + + val bindingContext = expression.analyzeInContext(scope) + + val thisType = symbolDescriptor.getExtensionReceiverParameter()?.getType() + ?: (symbolDescriptor.getContainingDeclaration() as? ClassifierDescriptor)?.getDefaultType() + + val receiversToAdd = ArrayList>() + + val parameterUsageKey = Key("parameterUsageKey") + + expression.accept(object : JetVisitorVoid(){ + override fun visitSimpleNameExpression(expression: JetSimpleNameExpression) { + val target = bindingContext[BindingContext.REFERENCE_TARGET, expression] ?: return + + if (target.canBeReferencedViaImport()) { + if (target.isExtension || expression.getReceiverExpression() == null) { + importFqNames.addIfNotNull(target.importableFqName) + } + } + + if (expression.getReceiverExpression() == null) { + if (target is ValueParameterDescriptor && target.getContainingDeclaration() == symbolDescriptor) { + expression.putCopyableUserData(parameterUsageKey, target) + } + + val resolvedCall = expression.getResolvedCall(bindingContext) + if (resolvedCall != null && resolvedCall.getStatus().isSuccess()) { + val receiver = if (resolvedCall.getResultingDescriptor().isExtension) + resolvedCall.getExtensionReceiver() + else + resolvedCall.getDispatchReceiver() + if (receiver is ThisReceiver) { + if (receiver.getType() == thisType) { + receiversToAdd.add(expression to "this") + } + else { + val descriptor = receiver.getDeclarationDescriptor() + if (descriptor is ClassDescriptor && descriptor.isCompanionObject()) { + receiversToAdd.add(expression to IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(descriptor)) + } + } + } + } + } + } + + override fun visitJetElement(element: JetElement) { + element.acceptChildren(this) + } + }) + + for ((expr, receiverText) in receiversToAdd) { + val expressionToReplace = expr.getParent() as? JetCallExpression ?: expr + val newExpr = expressionToReplace.replaced(psiFactory.createExpressionByPattern("$receiverText.$0", expressionToReplace)) + if (expressionToReplace == expression) { + expression = newExpr + } + } + + val parameterUsages = symbolDescriptor.getValueParameters() + .map { parameter -> parameter to expression.collectElementsOfType { it.getCopyableUserData(parameterUsageKey) == parameter } } + .toMap() + + expression.accept(object : PsiRecursiveElementVisitor() { + override fun visitElement(element: PsiElement) { + element.putCopyableUserData(parameterUsageKey, null) + } + }) + + return ReplacementExpression(expression, importFqNames, parameterUsages) + } + + private fun getResolutionScope(descriptor: DeclarationDescriptor): JetScope { + return when (descriptor) { + is PackageFragmentDescriptor -> { + val moduleDescriptor = descriptor.getContainingDeclaration() + getResolutionScope(moduleDescriptor.getPackage(descriptor.fqName)!!) + } + + is PackageViewDescriptor -> + descriptor.getMemberScope() + + is ClassDescriptorWithResolutionScopes -> + descriptor.getScopeForMemberDeclarationResolution() + + is FunctionDescriptor -> + FunctionDescriptorUtil.getFunctionInnerScope(getResolutionScope(descriptor.getContainingDeclaration()), + descriptor, RedeclarationHandler.DO_NOTHING) + + is PropertyDescriptor -> + JetScopeUtils.getPropertyDeclarationInnerScope(descriptor, + getResolutionScope(descriptor.getContainingDeclaration()!!), + RedeclarationHandler.DO_NOTHING) + + else -> throw IllegalArgumentException("Cannot find resolution scope for $descriptor") + } + } + + private class ExplicitImportsScope(val descriptors: Collection) : JetScope { + override fun getClassifier(name: Name) = descriptors.filter { it.getName() == name }.firstIsInstanceOrNull() + + override fun getPackage(name: Name)= descriptors.filter { it.getName() == name }.firstIsInstanceOrNull() + + override fun getProperties(name: Name) = descriptors.filter { it.getName() == name }.filterIsInstance() + + override fun getLocalVariable(name: Name): VariableDescriptor? = null + + override fun getFunctions(name: Name) = descriptors.filter { it.getName() == name }.filterIsInstance() + + override fun getContainingDeclaration() = throw UnsupportedOperationException() + + override fun getDeclarationsByLabel(labelName: Name) = emptyList() + + override fun getDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) = descriptors + + override fun getImplicitReceiversHierarchy() = emptyList() + + override fun getOwnDeclaredDescriptors() = emptyList() + + override fun printScopeStructure(p: Printer) { + p.println(javaClass.getName()) + } + } +} \ No newline at end of file