From aed5b934f84fccff8d1c893aa475bc9ce7bd1f0e Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 20 Jun 2017 19:48:46 +0300 Subject: [PATCH] Introduce KotlinBuiltIns.isUnderKotlinPackage Semantics is the same as in the former FunctionDescriptor.hasSubpackageOfKotlin, but it doesn't compute the FQ name of the descriptor --- .../calls/checkers/OperatorCallChecker.kt | 18 +++++------------- .../evaluate/ConstantExpressionEvaluator.kt | 4 +--- .../kotlin/resolve/deprecationUtil.kt | 3 +-- .../descriptors/LazyJavaClassDescriptor.kt | 4 ++-- .../kotlin/builtins/KotlinBuiltIns.java | 14 ++++++++++++++ .../src/org/jetbrains/kotlin/name/FqName.java | 4 ++++ 6 files changed, 27 insertions(+), 20 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/OperatorCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/OperatorCallChecker.kt index fd5645fa9f7..e8a0e57e352 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/OperatorCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/OperatorCallChecker.kt @@ -24,7 +24,6 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.Errors -import org.jetbrains.kotlin.name.isSubpackageOf import org.jetbrains.kotlin.psi.Call import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry @@ -34,7 +33,6 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isConventionCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.expressions.OperatorConventions @@ -105,22 +103,17 @@ fun FunctionDescriptor.isOperatorMod(): Boolean { return this.isOperator && name in OperatorConventions.REM_TO_MOD_OPERATION_NAMES.values } -// This is an alternate function to KotlinBuiltIns.isBuiltIn -// It is safer as it produces stable results independent of target platform (Java/JS/Native) -fun FunctionDescriptor.hasSubpackageOfKotlin(): Boolean { - val descriptorFqName = fqNameOrNull() ?: return false - return descriptorFqName.isSubpackageOf(KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME) -} - fun shouldWarnAboutDeprecatedModFromBuiltIns(languageVersionSettings: LanguageVersionSettings): Boolean { return languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem) && languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_1 } -private fun checkModConvention(descriptor: FunctionDescriptor, languageVersionSettings: LanguageVersionSettings, - diagnosticHolder: DiagnosticSink, modifier: PsiElement) { +private fun checkModConvention( + descriptor: FunctionDescriptor, languageVersionSettings: LanguageVersionSettings, + diagnosticHolder: DiagnosticSink, modifier: PsiElement +) { if (!descriptor.isOperatorMod()) return - if (descriptor.hasSubpackageOfKotlin()) { + if (KotlinBuiltIns.isUnderKotlinPackage(descriptor)) { if (shouldWarnAboutDeprecatedModFromBuiltIns(languageVersionSettings)) { addWarningAboutDeprecatedMod(descriptor, diagnosticHolder, modifier) } @@ -136,4 +129,3 @@ private fun addWarningAboutDeprecatedMod(descriptor: FunctionDescriptor, diagnos val newNameConvention = OperatorConventions.REM_TO_MOD_OPERATION_NAMES.inverse()[descriptor.name] diagnosticHolder.report(Errors.DEPRECATED_BINARY_MOD_AS_REM.on(reportOn, descriptor, newNameConvention!!.asString())) } - diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt index ddaea6ca746..621657ad2c2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt @@ -473,9 +473,7 @@ private class ConstantExpressionEvaluatorVisitor( private fun evaluateCall(callExpression: KtExpression, receiverExpression: KtExpression, expectedType: KotlinType?): CompileTimeConstant<*>? { val resolvedCall = callExpression.getResolvedCall(trace.bindingContext) ?: return null - - val descriptorFqName = resolvedCall.resultingDescriptor.fqNameOrNull() ?: return null - if (!descriptorFqName.isSubpackageOf(KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME)) return null + if (!KotlinBuiltIns.isUnderKotlinPackage(resolvedCall.resultingDescriptor)) return null val resultingDescriptorName = resolvedCall.resultingDescriptor.name diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt index e803a77fec4..6e2c9d21b36 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt @@ -30,7 +30,6 @@ import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.DeprecationLevelValue.* import org.jetbrains.kotlin.resolve.annotations.argumentValue -import org.jetbrains.kotlin.resolve.calls.checkers.hasSubpackageOfKotlin import org.jetbrains.kotlin.resolve.calls.checkers.isOperatorMod import org.jetbrains.kotlin.resolve.calls.checkers.shouldWarnAboutDeprecatedModFromBuiltIns import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe @@ -190,7 +189,7 @@ private fun deprecationByOverridden(root: CallableMemberDescriptor, languageVers private fun DeclarationDescriptor.getOwnDeprecations(languageVersionSettings: LanguageVersionSettings): List { // The problem is that declaration `mod` in built-ins has @Deprecated annotation but actually it was deprecated only in version 1.1 - if (this is FunctionDescriptor && this.isOperatorMod() && this.hasSubpackageOfKotlin()) { + if (this is FunctionDescriptor && this.isOperatorMod() && KotlinBuiltIns.isUnderKotlinPackage(this)) { if (!shouldWarnAboutDeprecatedModFromBuiltIns(languageVersionSettings)) { return emptyList() } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt index 1ddf7165f32..ced8d9ed4f2 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt @@ -210,8 +210,8 @@ class LazyJavaClassDescriptor( } private fun getPurelyImplementedSupertype(): KotlinType? { - val annotatedPurelyImplementedFqName = getPurelyImplementsFqNameFromAnnotation()?.takeIf { - !it.isRoot && it.toUnsafe().startsWith(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME) + val annotatedPurelyImplementedFqName = getPurelyImplementsFqNameFromAnnotation()?.takeIf { fqName -> + !fqName.isRoot && fqName.startsWith(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME) } val purelyImplementedFqName = diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java index 0b88ccbaa66..a0529d2458a 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java @@ -381,6 +381,20 @@ public abstract class KotlinBuiltIns { return DescriptorUtils.getParentOfType(descriptor, BuiltInsPackageFragment.class, false) != null; } + /** + * @return true if the containing package of the descriptor is "kotlin" or any subpackage of "kotlin" + */ + public static boolean isUnderKotlinPackage(@NotNull DeclarationDescriptor descriptor) { + DeclarationDescriptor current = descriptor; + while (current != null) { + if (current instanceof PackageFragmentDescriptor) { + return ((PackageFragmentDescriptor) current).getFqName().startsWith(BUILT_INS_PACKAGE_NAME); + } + current = current.getContainingDeclaration(); + } + return false; + } + @NotNull public MemberScope getBuiltInsPackageScope() { return packageFragments.invoke().builtInsPackageFragment.getMemberScope(); diff --git a/core/descriptors/src/org/jetbrains/kotlin/name/FqName.java b/core/descriptors/src/org/jetbrains/kotlin/name/FqName.java index 6722f764b66..6bd261e87d7 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/name/FqName.java +++ b/core/descriptors/src/org/jetbrains/kotlin/name/FqName.java @@ -98,6 +98,10 @@ public final class FqName { return fqName.pathSegments(); } + public boolean startsWith(@NotNull Name segment) { + return fqName.startsWith(segment); + } + @NotNull public static FqName topLevel(@NotNull Name shortName) { return new FqName(FqNameUnsafe.topLevel(shortName));