Write "pre-release" flag to class files, do not allow usages in release

This commit is contained in:
Alexander Udalov
2016-12-07 14:22:29 +03:00
parent 1342743001
commit 4e99349f1f
13 changed files with 125 additions and 36 deletions
@@ -41,7 +41,9 @@ class WrongBytecodeVersionTest : KtUsefulTestCase() {
LoadDescriptorUtil.compileKotlinToDirAndGetModule(listOf(librarySource), tmpdir, environment)
for (classFile in File(tmpdir, "library").listFiles { file -> file.extension == JavaClassFileType.INSTANCE.defaultExtension }) {
changeVersionInBytecode(classFile)
classFile.writeBytes(transformMetadataInClassFile(classFile.readBytes()) { name, _ ->
if (name == JvmAnnotationNames.BYTECODE_VERSION_FIELD_NAME) incompatibleVersion else null
})
}
val (output, exitCode) = AbstractCliTest.executeCompilerGrabOutput(K2JVMCompiler(), listOf(
@@ -57,28 +59,27 @@ class WrongBytecodeVersionTest : KtUsefulTestCase() {
KotlinTestUtils.assertEqualsToFile(File(directory, "output.txt"), normalized)
}
private fun changeVersionInBytecode(file: File) {
val writer = ClassWriter(0)
ClassReader(file.inputStream()).accept(object : ClassVisitor(Opcodes.ASM5, writer) {
override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? {
val superVisitor = super.visitAnnotation(desc, visible)!!
if (desc == JvmAnnotationNames.METADATA_DESC) {
return object : AnnotationVisitor(Opcodes.ASM5, superVisitor) {
override fun visit(name: String?, value: Any) {
val updatedValue: Any =
if (name == JvmAnnotationNames.BYTECODE_VERSION_FIELD_NAME) incompatibleVersion
else value
super.visit(name, updatedValue)
}
}
}
return superVisitor
}
}, 0)
file.writeBytes(writer.toByteArray())
}
fun testSimple() {
doTest("/bytecodeVersion/simple")
}
companion object {
fun transformMetadataInClassFile(bytes: ByteArray, transform: (fieldName: String, value: Any?) -> Any?): ByteArray {
val writer = ClassWriter(0)
ClassReader(bytes).accept(object : ClassVisitor(Opcodes.ASM5, writer) {
override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor {
val superVisitor = super.visitAnnotation(desc, visible)
if (desc == JvmAnnotationNames.METADATA_DESC) {
return object : AnnotationVisitor(Opcodes.ASM5, superVisitor) {
override fun visit(name: String, value: Any) {
super.visit(name, transform(name, value) ?: value)
}
}
}
return superVisitor
}
}, 0)
return writer.toByteArray()
}
}
}
@@ -34,8 +34,10 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil;
import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.config.KotlinCompilerVersion;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor;
import org.jetbrains.kotlin.load.kotlin.DeserializedDescriptorResolver;
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
@@ -226,6 +228,31 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir {
KotlinTestUtils.assertEqualsToFile(new File(getTestDataDirectory(), "output.txt"), normalizeOutput(output));
}
@SuppressWarnings("deprecation")
private void doTestPreReleaseKotlinLibrary(@NotNull String libraryName) throws Exception {
// Compiles the library with the "pre-release" flag, then compiles a usage of this library in the release mode
File library;
try {
DeserializedDescriptorResolver.Companion.setIS_PRE_RELEASE(true);
library = compileLibrary(libraryName);
}
finally {
DeserializedDescriptorResolver.Companion.setIS_PRE_RELEASE(KotlinCompilerVersion.IS_PRE_RELEASE);
}
Pair<String, ExitCode> output;
try {
DeserializedDescriptorResolver.Companion.setIS_PRE_RELEASE(false);
output = compileKotlin("source.kt", tmpdir, library);
}
finally {
DeserializedDescriptorResolver.Companion.setIS_PRE_RELEASE(KotlinCompilerVersion.IS_PRE_RELEASE);
}
KotlinTestUtils.assertEqualsToFile(new File(getTestDataDirectory(), "output.txt"), normalizeOutput(output));
}
// ------------------------------------------------------------------------------
public void testRawTypes() throws Exception {
@@ -337,6 +364,10 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir {
doTestBrokenJavaLibrary("library", "test/A$Anno.class");
}
public void testReleaseCompilerAgainstPreReleaseLibrary() throws Exception {
doTestPreReleaseKotlinLibrary("library");
}
/*test source mapping generation when source info is absent*/
public void testInlineFunWithoutDebugInfo() throws Exception {
compileKotlin("sourceInline.kt", tmpdir);