Generate not-null assertions on extension receiver parameters
This commit is contained in:
@@ -597,18 +597,33 @@ public class AsmUtil {
|
|||||||
// Private method is not accessible from other classes, no assertions needed
|
// Private method is not accessible from other classes, no assertions needed
|
||||||
if (getVisibilityAccessFlag(descriptor) == ACC_PRIVATE) return;
|
if (getVisibilityAccessFlag(descriptor) == ACC_PRIVATE) return;
|
||||||
|
|
||||||
for (ValueParameterDescriptor parameter : descriptor.getValueParameters()) {
|
ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter();
|
||||||
JetType type = parameter.getReturnType();
|
if (receiverParameter != null) {
|
||||||
if (type == null || isNullableType(type)) continue;
|
genParamAssertion(v, state.getTypeMapper(), frameMap, receiverParameter, "$receiver");
|
||||||
|
}
|
||||||
|
|
||||||
int index = frameMap.getIndex(parameter);
|
for (ValueParameterDescriptor parameter : descriptor.getValueParameters()) {
|
||||||
Type asmType = state.getTypeMapper().mapType(type);
|
genParamAssertion(v, state.getTypeMapper(), frameMap, parameter, parameter.getName().asString());
|
||||||
if (asmType.getSort() == Type.OBJECT || asmType.getSort() == Type.ARRAY) {
|
}
|
||||||
v.load(index, asmType);
|
}
|
||||||
v.visitLdcInsn(parameter.getName().asString());
|
|
||||||
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "checkParameterIsNotNull",
|
private static void genParamAssertion(
|
||||||
"(Ljava/lang/Object;Ljava/lang/String;)V", false);
|
@NotNull InstructionAdapter v,
|
||||||
}
|
@NotNull JetTypeMapper typeMapper,
|
||||||
|
@NotNull FrameMap frameMap,
|
||||||
|
@NotNull CallableDescriptor parameter,
|
||||||
|
@NotNull String name
|
||||||
|
) {
|
||||||
|
JetType type = parameter.getReturnType();
|
||||||
|
if (type == null || isNullableType(type)) return;
|
||||||
|
|
||||||
|
int index = frameMap.getIndex(parameter);
|
||||||
|
Type asmType = typeMapper.mapType(type);
|
||||||
|
if (asmType.getSort() == Type.OBJECT || asmType.getSort() == Type.ARRAY) {
|
||||||
|
v.load(index, asmType);
|
||||||
|
v.visitLdcInsn(name);
|
||||||
|
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "checkParameterIsNotNull",
|
||||||
|
"(Ljava/lang/Object;Ljava/lang/String;)V", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -731,7 +731,13 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (JvmMethodParameterSignature parameter : signature.getValueParameters()) {
|
for (JvmMethodParameterSignature parameter : signature.getValueParameters()) {
|
||||||
if (parameter.getKind() != JvmMethodParameterKind.VALUE) {
|
if (parameter.getKind() == JvmMethodParameterKind.RECEIVER) {
|
||||||
|
ReceiverParameterDescriptor receiverParameter = function.getExtensionReceiverParameter();
|
||||||
|
if (receiverParameter != null) {
|
||||||
|
frameMap.enter(receiverParameter, state.getTypeMapper().mapType(receiverParameter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (parameter.getKind() != JvmMethodParameterKind.VALUE) {
|
||||||
frameMap.enterTemp(parameter.getAsmType());
|
frameMap.enterTemp(parameter.getAsmType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
public class Test {
|
||||||
|
public static String invokeFoo() {
|
||||||
|
try {
|
||||||
|
_DefaultPackage.foo(null);
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
|
try {
|
||||||
|
_DefaultPackage.getBar(null);
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException f) {
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Fail: assertion must have been fired";
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
fun Any.foo() { }
|
||||||
|
|
||||||
|
val Any.bar: String get() = ""
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return Test.invokeFoo()
|
||||||
|
}
|
||||||
@@ -22,6 +22,8 @@ import com.intellij.psi.PsiFile;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult;
|
import org.jetbrains.kotlin.analyzer.AnalysisResult;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
|
import org.jetbrains.kotlin.codegen.state.Progress;
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink;
|
||||||
import org.jetbrains.kotlin.psi.JetFile;
|
import org.jetbrains.kotlin.psi.JetFile;
|
||||||
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil;
|
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil;
|
||||||
|
|
||||||
@@ -58,8 +60,12 @@ public class GenerationUtils {
|
|||||||
@NotNull List<JetFile> files
|
@NotNull List<JetFile> files
|
||||||
) {
|
) {
|
||||||
analysisResult.throwIfError();
|
analysisResult.throwIfError();
|
||||||
GenerationState state = new GenerationState(project, ClassBuilderFactories.TEST, analysisResult.getModuleDescriptor(),
|
GenerationState state = new GenerationState(
|
||||||
analysisResult.getBindingContext(), files);
|
project, ClassBuilderFactories.TEST, Progress.DEAF,
|
||||||
|
analysisResult.getModuleDescriptor(), analysisResult.getBindingContext(),
|
||||||
|
files, false, false, GenerationState.GenerateClassFilter.GENERATE_ALL,
|
||||||
|
false, false, null, null, DiagnosticSink.DO_NOTHING, null
|
||||||
|
);
|
||||||
KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION);
|
KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-1
@@ -30,7 +30,7 @@ import java.util.regex.Pattern;
|
|||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
@TestMetadata("compiler/testData/codegen/boxWithJava")
|
@TestMetadata("compiler/testData/codegen/boxWithJava")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@InnerTestClasses({BlackBoxWithJavaCodegenTestGenerated.BuiltinStubMethods.class, BlackBoxWithJavaCodegenTestGenerated.PlatformStatic.class, BlackBoxWithJavaCodegenTestGenerated.Properties.class})
|
@InnerTestClasses({BlackBoxWithJavaCodegenTestGenerated.BuiltinStubMethods.class, BlackBoxWithJavaCodegenTestGenerated.NotNullAssertions.class, BlackBoxWithJavaCodegenTestGenerated.PlatformStatic.class, BlackBoxWithJavaCodegenTestGenerated.Properties.class})
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||||
public void testAllFilesPresentInBoxWithJava() throws Exception {
|
public void testAllFilesPresentInBoxWithJava() throws Exception {
|
||||||
@@ -84,6 +84,23 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/boxWithJava/notNullAssertions")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@InnerTestClasses({})
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class NotNullAssertions extends AbstractBlackBoxCodegenTest {
|
||||||
|
public void testAllFilesPresentInNotNullAssertions() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithJava/notNullAssertions"), Pattern.compile("^([^\\.]+)$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extensionReceiverParameter")
|
||||||
|
public void testExtensionReceiverParameter() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/notNullAssertions/extensionReceiverParameter/");
|
||||||
|
doTestWithJava(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxWithJava/platformStatic")
|
@TestMetadata("compiler/testData/codegen/boxWithJava/platformStatic")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@InnerTestClasses({})
|
@InnerTestClasses({})
|
||||||
|
|||||||
Reference in New Issue
Block a user