From ccae0311c321931c4632d109e360dea1515f4f35 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 15 Apr 2015 22:47:30 +0300 Subject: [PATCH] Merge InlineDescriptorUtils to InlineUtil --- .../kotlin/codegen/JvmCodegenUtil.java | 4 +- .../kotlin/resolve/InlineDescriptorUtils.java | 109 ------------------ .../resolve/calls/checkers/InlineChecker.java | 4 +- .../kotlin/resolve/calls/util/callUtil.kt | 6 +- .../kotlin/resolve/inline/InlineUtil.java | 96 ++++++++++++++- .../ControlStructureTypingVisitor.java | 14 ++- 6 files changed, 107 insertions(+), 126 deletions(-) delete mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/InlineDescriptorUtils.java diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java index 552d1441648..7fcbc6bfb53 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java @@ -41,8 +41,8 @@ import org.jetbrains.kotlin.psi.codeFragmentUtil.CodeFragmentUtilPackage; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.DescriptorUtils; -import org.jetbrains.kotlin.resolve.InlineDescriptorUtils; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; +import org.jetbrains.kotlin.resolve.inline.InlineUtil; import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor; import org.jetbrains.kotlin.types.JetType; @@ -235,7 +235,7 @@ public class JvmCodegenUtil { PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor); return declaration instanceof JetFunctionLiteral && declaration.getParent() instanceof JetFunctionLiteralExpression && - InlineDescriptorUtils.isInlineLambda((JetFunctionLiteralExpression) declaration.getParent(), bindingContext, false); + InlineUtil.isInlineLambda((JetFunctionLiteralExpression) declaration.getParent(), bindingContext, false); } @Nullable diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/InlineDescriptorUtils.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/InlineDescriptorUtils.java deleted file mode 100644 index b97e5b922f4..00000000000 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/InlineDescriptorUtils.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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.resolve; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.util.PsiTreeUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.descriptors.*; -import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage; -import org.jetbrains.kotlin.resolve.calls.model.ArgumentMapping; -import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch; -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; -import org.jetbrains.kotlin.resolve.inline.InlineUtil; - -public class InlineDescriptorUtils { - - public static boolean checkNonLocalReturnUsage(@NotNull DeclarationDescriptor fromFunction, @NotNull JetExpression startExpression, @NotNull BindingTrace trace) { - PsiElement containingFunction = PsiTreeUtil.getParentOfType(startExpression, JetClassOrObject.class, JetDeclarationWithBody.class); - if (containingFunction == null) { - return false; - } - - DeclarationDescriptor containingFunctionDescriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, containingFunction); - if (containingFunctionDescriptor == null) { - return false; - } - - BindingContext bindingContext = trace.getBindingContext(); - - while (containingFunction instanceof JetFunctionLiteral && fromFunction != containingFunctionDescriptor) { - //JetFunctionLiteralExpression - containingFunction = containingFunction.getParent(); - if (!isInlineLambda((JetFunctionLiteralExpression) containingFunction, bindingContext, true)) { - return false; - } - - containingFunctionDescriptor = getContainingClassOrFunctionDescriptor(containingFunctionDescriptor, true); - - containingFunction = containingFunctionDescriptor != null - ? DescriptorToSourceUtils.descriptorToDeclaration(containingFunctionDescriptor) - : null; - } - - return fromFunction == containingFunctionDescriptor; - } - - public static boolean isInlineLambda( - @NotNull JetFunctionLiteralExpression lambdaExpression, - @NotNull BindingContext bindingContext, - boolean checkNonLocalReturn - ) { - JetExpression call = JetPsiUtil.getParentCallIfPresent(lambdaExpression); - if (call != null) { - ResolvedCall resolvedCall = CallUtilPackage.getResolvedCall(call, bindingContext); - if (resolvedCall != null && InlineUtil.isInline(resolvedCall.getResultingDescriptor())) { - ValueArgument argument = CallUtilPackage.getValueArgumentForExpression(resolvedCall.getCall(), lambdaExpression); - if (argument != null) { - ArgumentMapping mapping = resolvedCall.getArgumentMapping(argument); - if (mapping instanceof ArgumentMatch) { - ValueParameterDescriptor parameter = ((ArgumentMatch) mapping).getValueParameter(); - if (InlineUtil.isInlineLambdaParameter(parameter)) { - return !checkNonLocalReturn || allowsNonLocalReturns(parameter); - } - } - } - } - } - return false; - } - - @Nullable - public static DeclarationDescriptor getContainingClassOrFunctionDescriptor(@NotNull DeclarationDescriptor descriptor, boolean strict) { - DeclarationDescriptor currentDescriptor = strict ? descriptor.getContainingDeclaration() : descriptor; - while (currentDescriptor != null) { - if (currentDescriptor instanceof FunctionDescriptor || currentDescriptor instanceof ClassDescriptor) { - return currentDescriptor; - } - currentDescriptor = currentDescriptor.getContainingDeclaration(); - } - - return null; - } - - public static boolean allowsNonLocalReturns(@NotNull CallableDescriptor lambdaDescriptor) { - if (lambdaDescriptor instanceof ValueParameterDescriptor) { - if (InlineUtil.hasOnlyLocalReturn((ValueParameterDescriptor) lambdaDescriptor)) { - //annotated - return false; - } - } - return true; - } -} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java index 0fae77baca6..8e7cda34db0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java @@ -43,9 +43,9 @@ import java.util.Set; import static org.jetbrains.kotlin.diagnostics.Errors.NON_LOCAL_RETURN_NOT_ALLOWED; import static org.jetbrains.kotlin.diagnostics.Errors.USAGE_IS_NOT_INLINABLE; -import static org.jetbrains.kotlin.resolve.InlineDescriptorUtils.allowsNonLocalReturns; -import static org.jetbrains.kotlin.resolve.InlineDescriptorUtils.checkNonLocalReturnUsage; import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getIsEffectivelyPublicApi; +import static org.jetbrains.kotlin.resolve.inline.InlineUtil.allowsNonLocalReturns; +import static org.jetbrains.kotlin.resolve.inline.InlineUtil.checkNonLocalReturnUsage; class InlineChecker implements CallChecker { private final SimpleFunctionDescriptor descriptor; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt index d8a1c085a3d..f3b153c8a13 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt @@ -25,13 +25,13 @@ import org.jetbrains.kotlin.psi.psiUtil.getTextWithLocation import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext.CALL import org.jetbrains.kotlin.resolve.BindingContext.RESOLVED_CALL -import org.jetbrains.kotlin.resolve.InlineDescriptorUtils import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatchStatus import org.jetbrains.kotlin.resolve.calls.model.ArgumentUnmapped import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.utils.sure // resolved call @@ -184,5 +184,5 @@ public fun JetFunctionLiteral.isInlined(bindingContext: BindingContext): Boolean val parent = this.getParent() assert(parent is JetFunctionLiteralExpression) { "parent of JetFunctionLiteral is " + parent } - return InlineDescriptorUtils.isInlineLambda(parent as JetFunctionLiteralExpression, bindingContext, false) -} \ No newline at end of file + return InlineUtil.isInlineLambda(parent as JetFunctionLiteralExpression, bindingContext, false) +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineUtil.java index fc58a2b6806..497ee5aa433 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineUtil.java @@ -16,15 +16,22 @@ package org.jetbrains.kotlin.resolve.inline; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; -import org.jetbrains.kotlin.descriptors.CallableDescriptor; -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; -import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor; -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; +import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.kotlin.psi.*; +import org.jetbrains.kotlin.resolve.BindingContext; +import org.jetbrains.kotlin.resolve.BindingTrace; +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.DescriptorUtils; +import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage; +import org.jetbrains.kotlin.resolve.calls.model.ArgumentMapping; +import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch; +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.constants.ArrayValue; import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; import org.jetbrains.kotlin.resolve.constants.EnumValue; @@ -83,4 +90,85 @@ public class InlineUtil { return false; } + + public static boolean checkNonLocalReturnUsage( + @NotNull DeclarationDescriptor fromFunction, + @NotNull JetExpression startExpression, + @NotNull BindingTrace trace + ) { + PsiElement containingFunction = PsiTreeUtil.getParentOfType(startExpression, JetClassOrObject.class, JetDeclarationWithBody.class); + if (containingFunction == null) { + return false; + } + + DeclarationDescriptor containingFunctionDescriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, containingFunction); + if (containingFunctionDescriptor == null) { + return false; + } + + BindingContext bindingContext = trace.getBindingContext(); + + while (containingFunction instanceof JetFunctionLiteral && fromFunction != containingFunctionDescriptor) { + //JetFunctionLiteralExpression + containingFunction = containingFunction.getParent(); + if (!isInlineLambda((JetFunctionLiteralExpression) containingFunction, bindingContext, true)) { + return false; + } + + containingFunctionDescriptor = getContainingClassOrFunctionDescriptor(containingFunctionDescriptor, true); + + containingFunction = containingFunctionDescriptor != null + ? DescriptorToSourceUtils.descriptorToDeclaration(containingFunctionDescriptor) + : null; + } + + return fromFunction == containingFunctionDescriptor; + } + + public static boolean isInlineLambda( + @NotNull JetFunctionLiteralExpression lambdaExpression, + @NotNull BindingContext bindingContext, + boolean checkNonLocalReturn + ) { + JetExpression call = JetPsiUtil.getParentCallIfPresent(lambdaExpression); + if (call != null) { + ResolvedCall resolvedCall = CallUtilPackage.getResolvedCall(call, bindingContext); + if (resolvedCall != null && isInline(resolvedCall.getResultingDescriptor())) { + ValueArgument argument = CallUtilPackage.getValueArgumentForExpression(resolvedCall.getCall(), lambdaExpression); + if (argument != null) { + ArgumentMapping mapping = resolvedCall.getArgumentMapping(argument); + if (mapping instanceof ArgumentMatch) { + ValueParameterDescriptor parameter = ((ArgumentMatch) mapping).getValueParameter(); + if (isInlineLambdaParameter(parameter)) { + return !checkNonLocalReturn || allowsNonLocalReturns(parameter); + } + } + } + } + } + return false; + } + + @Nullable + public static DeclarationDescriptor getContainingClassOrFunctionDescriptor(@NotNull DeclarationDescriptor descriptor, boolean strict) { + DeclarationDescriptor current = strict ? descriptor.getContainingDeclaration() : descriptor; + while (current != null) { + if (current instanceof FunctionDescriptor || current instanceof ClassDescriptor) { + return current; + } + current = current.getContainingDeclaration(); + } + + return null; + } + + public static boolean allowsNonLocalReturns(@NotNull CallableDescriptor lambda) { + if (lambda instanceof ValueParameterDescriptor) { + if (hasOnlyLocalReturn((ValueParameterDescriptor) lambda)) { + //annotated + return false; + } + } + return true; + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java index 457efa4d49d..70724f4e5d6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java @@ -28,10 +28,14 @@ import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.resolve.*; +import org.jetbrains.kotlin.resolve.BindingContext; +import org.jetbrains.kotlin.resolve.BindingContextUtils; +import org.jetbrains.kotlin.resolve.DescriptorResolver; +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; +import org.jetbrains.kotlin.resolve.inline.InlineUtil; import org.jetbrains.kotlin.resolve.scopes.JetScope; import org.jetbrains.kotlin.resolve.scopes.WritableScope; import org.jetbrains.kotlin.resolve.scopes.WritableScopeImpl; @@ -48,9 +52,7 @@ import static org.jetbrains.kotlin.diagnostics.Errors.*; import static org.jetbrains.kotlin.psi.PsiPackage.JetPsiFactory; import static org.jetbrains.kotlin.resolve.BindingContext.*; import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT; -import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE; -import static org.jetbrains.kotlin.types.TypeUtils.isDontCarePlaceholder; -import static org.jetbrains.kotlin.types.TypeUtils.noExpectedType; +import static org.jetbrains.kotlin.types.TypeUtils.*; import static org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction; import static org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createDataFlowInfoForArgumentsForIfCall; import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*; @@ -496,7 +498,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { FunctionDescriptor containingFunctionDescriptor = containingFunInfo.getFirst(); if (containingFunctionDescriptor != null) { - if (!InlineDescriptorUtils.checkNonLocalReturnUsage(containingFunctionDescriptor, expression, context.trace) || + if (!InlineUtil.checkNonLocalReturnUsage(containingFunctionDescriptor, expression, context.trace) || isClassInitializer(containingFunInfo)) { // Unqualified, in a function literal context.trace.report(RETURN_NOT_ALLOWED.on(expression)); @@ -515,7 +517,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { SimpleFunctionDescriptor functionDescriptor = context.trace.get(FUNCTION, labelTargetElement); if (functionDescriptor != null) { expectedType = getFunctionExpectedReturnType(functionDescriptor, labelTargetElement, context); - if (!InlineDescriptorUtils.checkNonLocalReturnUsage(functionDescriptor, expression, context.trace)) { + if (!InlineUtil.checkNonLocalReturnUsage(functionDescriptor, expression, context.trace)) { // Qualified, non-local context.trace.report(RETURN_NOT_ALLOWED.on(expression)); resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);