Diagnostic for nullable parameter of Function type
This commit is contained in:
+12
-14
@@ -37,9 +37,9 @@ import java.util.*;
|
||||
|
||||
public class InlineCallResolverExtension implements CallResolverExtension {
|
||||
|
||||
private SimpleFunctionDescriptor descriptor;
|
||||
private final SimpleFunctionDescriptor descriptor;
|
||||
|
||||
private Set<DeclarationDescriptor> inlinableParameters = new HashSet<DeclarationDescriptor>();
|
||||
private final Set<CallableDescriptor> inlinableParameters = new HashSet<CallableDescriptor>();
|
||||
|
||||
private final boolean isEffectivelyPublicApiFunction;
|
||||
|
||||
@@ -48,21 +48,16 @@ public class InlineCallResolverExtension implements CallResolverExtension {
|
||||
this.descriptor = descriptor;
|
||||
this.isEffectivelyPublicApiFunction = isEffectivelyPublicApi(descriptor);
|
||||
|
||||
Iterator<ValueParameterDescriptor> iterator = descriptor.getValueParameters().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
ValueParameterDescriptor next = iterator.next();
|
||||
JetType type = next.getType();
|
||||
if (KotlinBuiltIns.getInstance().isExactFunctionOrExtensionFunctionType(type)) {
|
||||
if (!InlineUtil.hasNoinlineAnnotation(next)) {
|
||||
inlinableParameters.add(next);
|
||||
}
|
||||
for (ValueParameterDescriptor param : descriptor.getValueParameters()) {
|
||||
if (isInlinableParameter(param)) {
|
||||
inlinableParameters.add(param);
|
||||
}
|
||||
}
|
||||
|
||||
//add extension receiver as inlineable
|
||||
ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
|
||||
if (receiverParameter != null) {
|
||||
if (isExactFunctionOrExtensionFunctionType(receiverParameter.getType())) {
|
||||
if (isInlinableParameter(receiverParameter)) {
|
||||
inlinableParameters.add(receiverParameter);
|
||||
}
|
||||
}
|
||||
@@ -178,9 +173,12 @@ public class InlineCallResolverExtension implements CallResolverExtension {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean isExactFunctionOrExtensionFunctionType(@NotNull JetType type) {
|
||||
return KotlinBuiltIns.getInstance().isExactFunctionOrExtensionFunctionType(type);
|
||||
private boolean isInlinableParameter(@NotNull CallableDescriptor descriptor) {
|
||||
JetType type = descriptor.getReturnType();
|
||||
return type != null &&
|
||||
KotlinBuiltIns.getInstance().isExactFunctionOrExtensionFunctionType(type) &&
|
||||
!type.isNullable() &&
|
||||
!InlineUtil.hasNoinlineAnnotation(descriptor);
|
||||
}
|
||||
|
||||
private static boolean isInvokeOrInlineExtension(@NotNull CallableDescriptor descriptor) {
|
||||
|
||||
+31
-13
@@ -22,6 +22,7 @@ import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.FunctionAnalyzerExtension;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.InlineUtil;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
|
||||
@@ -44,7 +45,7 @@ public class InlineAnalyzerExtension implements FunctionAnalyzerExtension.Analyz
|
||||
|
||||
checkDefaults(descriptor, function, trace);
|
||||
checkModality(descriptor, function, trace);
|
||||
checkHashInlinable(descriptor, function, trace);
|
||||
checkHashInlinableAndNullability(descriptor, function, trace);
|
||||
|
||||
JetVisitorVoid visitor = new JetVisitorVoid() {
|
||||
|
||||
@@ -106,28 +107,45 @@ public class InlineAnalyzerExtension implements FunctionAnalyzerExtension.Analyz
|
||||
trace.report(Errors.DECLARATION_CANT_BE_INLINED.on(function));
|
||||
}
|
||||
|
||||
private void checkHashInlinable(
|
||||
private void checkHashInlinableAndNullability(
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull JetFunction function,
|
||||
@NotNull BindingTrace trace
|
||||
) {
|
||||
boolean hasInlinable = false;
|
||||
List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters();
|
||||
int index = 0;
|
||||
for (ValueParameterDescriptor parameter : parameters) {
|
||||
KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
|
||||
if (builtIns.isExactFunctionOrExtensionFunctionType(parameter.getType())) {
|
||||
if (!InlineUtil.hasNoinlineAnnotation(parameter)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
hasInlinable |= checkParameter(parameter, function.getValueParameters().get(index++), functionDescriptor, trace);
|
||||
}
|
||||
ReceiverParameterDescriptor receiverParameter = functionDescriptor.getReceiverParameter();
|
||||
if (receiverParameter != null) {
|
||||
if (KotlinBuiltIns.getInstance().isExactFunctionOrExtensionFunctionType(receiverParameter.getType())) {
|
||||
//or extension on inlinable function
|
||||
return;
|
||||
}
|
||||
JetTypeReference receiver = function.getReceiverTypeRef();
|
||||
hasInlinable |= checkParameter(receiverParameter, receiver, functionDescriptor, trace);
|
||||
}
|
||||
|
||||
trace.report(Errors.NOTHING_TO_INLINE.on(function, functionDescriptor));
|
||||
if (!hasInlinable) {
|
||||
trace.report(Errors.NOTHING_TO_INLINE.on(function, functionDescriptor));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkParameter(
|
||||
@NotNull CallableDescriptor parameter,
|
||||
@NotNull JetElement expression,
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull BindingTrace trace
|
||||
) {
|
||||
KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
|
||||
JetType type = parameter.getReturnType();
|
||||
if (type != null && builtIns.isExactFunctionOrExtensionFunctionType(type)) {
|
||||
if (!InlineUtil.hasNoinlineAnnotation(parameter)) {
|
||||
if (type.isNullable()) {
|
||||
trace.report(Errors.NULLABLE_INLINE_PARAMETER.on(expression, expression, functionDescriptor));
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||
|
||||
public inline fun <T> <!NULLABLE_INLINE_PARAMETER!>Function1<Int, Int>?<!>.submit(action: ()->T) {
|
||||
this?.invoke(11)
|
||||
}
|
||||
|
||||
public inline fun <T> submit(<!NULLABLE_INLINE_PARAMETER!>action: Function1<Int, Int>?<!>, s: () -> Int) {
|
||||
action?.invoke(10)
|
||||
}
|
||||
|
||||
public inline fun <T> submitNoInline(noinline action: Function1<Int, Int>?, s: () -> Int) {
|
||||
action?.invoke(10)
|
||||
}
|
||||
|
||||
<!NOTHING_TO_INLINE!>public inline fun <T> <!NULLABLE_INLINE_PARAMETER!>Function1<Int, Int>?<!>.submit() {
|
||||
|
||||
}<!>
|
||||
|
||||
<!NOTHING_TO_INLINE!>public inline fun <T> submit(<!NULLABLE_INLINE_PARAMETER!>action: Function1<Int, Int>?<!>) {
|
||||
|
||||
}<!>
|
||||
@@ -3792,6 +3792,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
doTest("compiler/testData/diagnostics/tests/inline/nothingToInline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nullableFunction.kt")
|
||||
public void testNullableFunction() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inline/nullableFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propagation.kt")
|
||||
public void testPropagation() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inline/propagation.kt");
|
||||
|
||||
Reference in New Issue
Block a user