Merge InlineDescriptorUtils to InlineUtil
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
return InlineUtil.isInlineLambda(parent as JetFunctionLiteralExpression, bindingContext, false)
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+8
-6
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user