Frontend support for function as expression
This commit is contained in:
@@ -233,6 +233,9 @@ public interface Errors {
|
||||
|
||||
DiagnosticFactory0<PsiElement> REIFIED_TYPE_PARAMETER_NO_INLINE = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<JetDeclaration> TYPE_PARAMETERS_NOT_ALLOWED
|
||||
= DiagnosticFactory0.create(ERROR, TYPE_PARAMETERS_OR_DECLARATION_SIGNATURE);
|
||||
|
||||
// Members
|
||||
|
||||
DiagnosticFactory0<JetModifierListOwner> PACKAGE_MEMBER_CANNOT_BE_PROTECTED =
|
||||
@@ -339,6 +342,10 @@ public interface Errors {
|
||||
|
||||
DiagnosticFactory0<JetNamedFunction> NO_TAIL_CALLS_FOUND = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE);
|
||||
|
||||
DiagnosticFactory0<JetParameter> FUNCTION_EXPRESSION_PARAMETER_WITH_DEFAULT_VALUE = DiagnosticFactory0.create(ERROR, PARAMETER_DEFAULT_VALUE);
|
||||
|
||||
DiagnosticFactory0<JetParameter> USELESS_VARARG_ON_PARAMETER = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
// Named parameters
|
||||
|
||||
DiagnosticFactory0<JetParameter> DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE = DiagnosticFactory0.create(ERROR, PARAMETER_DEFAULT_VALUE);
|
||||
|
||||
@@ -168,6 +168,18 @@ public object PositioningStrategies {
|
||||
}
|
||||
}
|
||||
|
||||
public val TYPE_PARAMETERS_OR_DECLARATION_SIGNATURE: PositioningStrategy<JetDeclaration> = object : PositioningStrategy<JetDeclaration>() {
|
||||
override fun mark(element: JetDeclaration): List<TextRange> {
|
||||
if (element is JetTypeParameterListOwner) {
|
||||
val jetTypeParameterList = element.getTypeParameterList()
|
||||
if (jetTypeParameterList != null) {
|
||||
return markElement(jetTypeParameterList)
|
||||
}
|
||||
}
|
||||
return DECLARATION_SIGNATURE.mark(element)
|
||||
}
|
||||
}
|
||||
|
||||
public val ABSTRACT_MODIFIER: PositioningStrategy<JetModifierListOwner> = modifierSetPosition(JetTokens.ABSTRACT_KEYWORD)
|
||||
|
||||
public val INNER_MODIFIER: PositioningStrategy<JetModifierListOwner> = modifierSetPosition(JetTokens.INNER_KEYWORD)
|
||||
|
||||
+4
@@ -229,6 +229,9 @@ public class DefaultErrorMessages {
|
||||
|
||||
MAP.put(PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE, "Public or protected member should have specified type");
|
||||
|
||||
MAP.put(FUNCTION_EXPRESSION_PARAMETER_WITH_DEFAULT_VALUE, "A function expression is not allowed to specify default values for its parameters");
|
||||
MAP.put(USELESS_VARARG_ON_PARAMETER, "Vararg on this parameter is useless");
|
||||
|
||||
MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties");
|
||||
MAP.put(SUPERTYPE_NOT_INITIALIZED, "This type has a constructor, and thus must be initialized here");
|
||||
MAP.put(NOTHING_TO_OVERRIDE, "''{0}'' overrides nothing", NAME);
|
||||
@@ -570,6 +573,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(TYPE_PARAMETER_AS_REIFIED, "Cannot use ''{0}'' as reified type parameter. Use a class instead.", NAME);
|
||||
MAP.put(REIFIED_TYPE_PARAMETER_NO_INLINE, "Only type parameters of inline functions can be reified");
|
||||
MAP.put(REIFIED_TYPE_FORBIDDEN_SUBSTITUTION, "Cannot use ''{0}'' as reified type parameter", RENDER_TYPE);
|
||||
MAP.put(TYPE_PARAMETERS_NOT_ALLOWED, "Type parameters are not allowed here");
|
||||
|
||||
MAP.put(SUPERTYPES_FOR_ANNOTATION_CLASS, "Annotation class cannot have supertypes");
|
||||
MAP.put(MISSING_VAL_ON_ANNOTATION_PARAMETER, "'val' keyword is missing on annotation parameter");
|
||||
|
||||
@@ -241,7 +241,7 @@ public class DescriptorResolver {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SimpleFunctionDescriptor resolveAnonymousFunctionDescriptor(
|
||||
public SimpleFunctionDescriptor resolveFunctionExpressionDescriptor(
|
||||
@NotNull DeclarationDescriptor containingDescriptor,
|
||||
@NotNull JetScope scope,
|
||||
@NotNull JetNamedFunction function,
|
||||
|
||||
+68
-9
@@ -20,6 +20,8 @@ import com.google.common.collect.Lists;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import kotlin.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -29,6 +31,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
@@ -1302,22 +1305,78 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
boolean isStatement,
|
||||
@Nullable WritableScope statementScope // must be not null if isStatement
|
||||
) {
|
||||
SimpleFunctionDescriptor functionDescriptor = components.expressionTypingServices.getDescriptorResolver().
|
||||
resolveFunctionDescriptorWithAnnotationArguments(
|
||||
context.scope.getContainingDeclaration(), context.scope, function, context.trace, context.dataFlowInfo);
|
||||
if (!isStatement) { // function expression
|
||||
if (!function.getTypeParameters().isEmpty()) {
|
||||
context.trace.report(TYPE_PARAMETERS_NOT_ALLOWED.on(function));
|
||||
}
|
||||
for (JetParameter parameter : function.getValueParameters()) {
|
||||
if (parameter.hasDefaultValue()) {
|
||||
context.trace.report(FUNCTION_EXPRESSION_PARAMETER_WITH_DEFAULT_VALUE.on(parameter));
|
||||
}
|
||||
if (parameter.isVarArg()) {
|
||||
context.trace.report(USELESS_VARARG_ON_PARAMETER.on(parameter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExpressionTypingServices services = components.expressionTypingServices;
|
||||
|
||||
SimpleFunctionDescriptor functionDescriptor;
|
||||
if (isStatement) {
|
||||
functionDescriptor = services.getDescriptorResolver().
|
||||
resolveFunctionDescriptorWithAnnotationArguments(
|
||||
context.scope.getContainingDeclaration(), context.scope, function, context.trace, context.dataFlowInfo);
|
||||
assert statementScope != null : "statementScope must be not null for function: " +
|
||||
function.getName() +
|
||||
" at location " +
|
||||
DiagnosticUtils.atLocation(function);
|
||||
statementScope.addFunctionDescriptor(functionDescriptor);
|
||||
}
|
||||
else {
|
||||
functionDescriptor = services.getDescriptorResolver().resolveFunctionExpressionDescriptor(
|
||||
context.scope.getContainingDeclaration(), context.scope, function, context.trace, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
statementScope.addFunctionDescriptor(functionDescriptor);
|
||||
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace);
|
||||
components.expressionTypingServices.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo, null, context.trace);
|
||||
services.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo, null, context.trace);
|
||||
|
||||
components.expressionTypingServices.resolveValueParameters(function.getValueParameters(), functionDescriptor.getValueParameters(),
|
||||
context.scope, context.dataFlowInfo, context.trace);
|
||||
services.resolveValueParameters(function.getValueParameters(), functionDescriptor.getValueParameters(), context.scope,
|
||||
context.dataFlowInfo, context.trace);
|
||||
|
||||
ModifiersChecker.create(context.trace, components.additionalCheckerProvider).checkModifiersForLocalDeclaration(function, functionDescriptor);
|
||||
ModifiersChecker.create(context.trace, components.additionalCheckerProvider).checkModifiersForLocalDeclaration(function,
|
||||
functionDescriptor);
|
||||
if (!function.hasBody()) {
|
||||
context.trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor));
|
||||
}
|
||||
return DataFlowUtils.checkStatementType(function, context, context.dataFlowInfo);
|
||||
|
||||
if (isStatement) {
|
||||
return DataFlowUtils.checkStatementType(function, context, context.dataFlowInfo);
|
||||
}
|
||||
else {
|
||||
return DataFlowUtils.checkType(createFunctionType(functionDescriptor), function, context, context.dataFlowInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JetType createFunctionType(@NotNull SimpleFunctionDescriptor functionDescriptor) {
|
||||
JetType receiverType = functionDescriptor.getExtensionReceiverParameter() != null
|
||||
? functionDescriptor.getExtensionReceiverParameter().getType()
|
||||
: null;
|
||||
|
||||
JetType returnType = functionDescriptor.getReturnType();
|
||||
if (returnType == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<JetType> parameters =
|
||||
ContainerUtil.map(functionDescriptor.getValueParameters(), new Function<ValueParameterDescriptor, JetType>() {
|
||||
@Override
|
||||
public JetType fun(ValueParameterDescriptor descriptor) {
|
||||
return descriptor.getType();
|
||||
}
|
||||
});
|
||||
|
||||
return components.builtIns.getFunctionType(Annotations.EMPTY, receiverType, parameters, returnType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user