diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java index 6271554f57a..ec22cccfb9b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java @@ -66,7 +66,6 @@ public class AnonymousObjectTransformer extends ObjectTransformer") + (generateNodeText ? ("\nCause: " + InlineCodegenUtil.getNodeText(node)) : ""), e, callElement @@ -321,7 +322,7 @@ public class InlineCodegen extends CallGenerator { } }); - return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), classId, state); + return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), classId); } assert callableDescriptor instanceof DeserializedCallableMemberDescriptor : "Not a deserialized function or proper: " + callableDescriptor; @@ -348,7 +349,7 @@ public class InlineCodegen extends CallGenerator { }); - return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), containerId, state); + return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), containerId); } @NotNull diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java index 6de0d7e499f..a4a5e6c0fdb 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java @@ -92,8 +92,7 @@ public class InlineCodegenUtil { byte[] classData, final String methodName, final String methodDescriptor, - ClassId classId, - final @NotNull GenerationState state + ClassId classId ) { ClassReader cr = new ClassReader(classData); final MethodNode[] node = new MethodNode[1]; @@ -103,10 +102,6 @@ public class InlineCodegenUtil { lines[1] = Integer.MIN_VALUE; //noinspection PointlessBitwiseExpression cr.accept(new ClassVisitor(API) { - @Override - public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) { - assertVersionNotGreaterThanGeneratedOne(version, name, state); - } @Override public void visitSource(String source, String debug) { @@ -151,16 +146,6 @@ public class InlineCodegenUtil { return new SMAPAndMethodNode(node[0], smap); } - public static void assertVersionNotGreaterThanGeneratedOne(int version, String internalName, @NotNull GenerationState state) { - // TODO: report a proper diagnostic - if (version > state.getClassFileVersion() && !"true".equals(System.getProperty("kotlin.skip.bytecode.version.check"))) { - throw new UnsupportedOperationException( - "Cannot inline bytecode of class " + internalName + " which has version " + version + ". " + - "This compiler can only inline Java 1.6 bytecode (version " + Opcodes.V1_6 + ")" - ); - } - } - public static void initDefaultSourceMappingIfNeeded( @NotNull CodegenContext context, @NotNull MemberCodegen codegen, @NotNull GenerationState state ) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt index a69ed979a52..0fd9fffb725 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt @@ -66,7 +66,6 @@ class WhenMappingTransformer( val fieldNode = transformationInfo.fieldNode classReader.accept(object : ClassVisitor(InlineCodegenUtil.API, classBuilder.visitor) { override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array) { - InlineCodegenUtil.assertVersionNotGreaterThanGeneratedOne(version, name, state) classBuilder.defineClass(null, version, access, name, signature, superName, interfaces) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt index 694eb5c5c51..74b42cc681e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt @@ -123,7 +123,8 @@ class GenerationState @JvmOverloads constructor( extraJvmDiagnosticsTrace.bindingContext.diagnostics } - val isJvm8Target: Boolean = configuration.get(JVMConfigurationKeys.JVM_TARGET) == JvmTarget.JVM_1_8 + val target = configuration.get(JVMConfigurationKeys.JVM_TARGET) ?: JvmTarget.DEFAULT + val isJvm8Target: Boolean = target == JvmTarget.JVM_1_8 val isJvm8TargetWithDefaults: Boolean = isJvm8Target && configuration.getBoolean(JVMConfigurationKeys.JVM8_TARGET_WITH_DEFAULTS) val generateDefaultImplsForJvm8: Boolean = configuration.getBoolean(JVMConfigurationKeys.INTERFACE_COMPATIBILITY) @@ -162,7 +163,7 @@ class GenerationState @JvmOverloads constructor( val rootContext: CodegenContext<*> = RootContext(this) - val classFileVersion: Int = if (isJvm8Target) Opcodes.V1_8 else Opcodes.V1_6 + val classFileVersion: Int = target.bytecodeVersion val generateParametersMetadata: Boolean = configuration.getBoolean(JVMConfigurationKeys.PARAMETERS_METADATA) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/InlinePlatformCompatibilityChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/InlinePlatformCompatibilityChecker.kt new file mode 100644 index 00000000000..0e4304ede99 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/InlinePlatformCompatibilityChecker.kt @@ -0,0 +1,92 @@ +/* + * Copyright 2010-2017 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.jvm.checkers + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.config.JVMConfigurationKeys +import org.jetbrains.kotlin.config.JvmTarget +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.ClassOrPackageFragmentDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass +import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryPackageSourceElement +import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.inline.InlineUtil +import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor + +class InlinePlatformCompatibilityChecker: CallChecker { + + private val doCheck = doCheck() + + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { + if (!doCheck) return + + val resultingDescriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return + if (!InlineUtil.isInline(resultingDescriptor)) { + if (resultingDescriptor is PropertyDescriptor && InlineUtil.isInline(resultingDescriptor.getter)) { + //TODO: we should distinguish setter usage from getter one, now we could report wrong diagnostic on non-inline setter + //var prop: Int + // inline get + // set + // + // prop - resolved call with property descriptor and we should report error + // prop = 1 - resolved call with setter for whole expression and property descriptor for left part, + // so we couldn't distinguish is this expression for setter or for getter and will report wrong diagnostic + } + else { + return + } + } + + val propertyOrFun = DescriptorUtils.getDirectMember(resultingDescriptor) + val inliningBytecodeVersion = getBytecodeVersionIfDeserializedDescriptor(propertyOrFun) ?: return + + val compilingTarget = context.compilerConfiguration[JVMConfigurationKeys.JVM_TARGET] ?: JvmTarget.DEFAULT + val compilingBytecodeVersion = compilingTarget.bytecodeVersion + if (compilingBytecodeVersion < inliningBytecodeVersion) { + context.trace.report(ErrorsJvm.INLINE_FROM_HIGHER_PLATFORM.on(reportOn, JvmTarget.getDescription(inliningBytecodeVersion), JvmTarget.getDescription(compilingBytecodeVersion))) + } + } + + companion object { + + fun doCheck() = "true" != System.getProperty("kotlin.skip.bytecode.version.check") + + fun getBytecodeVersionIfDeserializedDescriptor(funOrProperty: DeclarationDescriptor): Int? { + if (funOrProperty !is DeserializedCallableMemberDescriptor) return null + + val containingDeclaration = funOrProperty.containingDeclaration as ClassOrPackageFragmentDescriptor + + val source = containingDeclaration.source + val binaryClass = + when (source) { + is KotlinJvmBinarySourceElement -> source.binaryClass + is KotlinJvmBinaryPackageSourceElement -> source.getContainingBinaryClass(funOrProperty) + else -> null + } as? FileBasedKotlinClass ?: return null + + return binaryClass.classVersion + } + } +} + diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java index 7cd003aa75a..fbc89c90a73 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java @@ -115,6 +115,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension { MAP.put(ErrorsJvm.DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET, "Super calls to Java default methods are deprecated in JVM target 1.6. Recompile with '-jvm-target 1.8'"); MAP.put(ErrorsJvm.INTERFACE_STATIC_METHOD_CALL_FROM_JAVA6_TARGET, "Calls to static methods in Java interfaces are deprecated in JVM target 1.6. Recompile with '-jvm-target 1.8'"); + + MAP.put(ErrorsJvm.INLINE_FROM_HIGHER_PLATFORM, "Cannot inline bytecode built with {0} into bytecode that is being built with {1}. Please specify proper ''-jvm-target'' option", Renderers.TO_STRING, Renderers.TO_STRING); } @NotNull diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java index a1f09d93c16..94064abf18e 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java @@ -92,6 +92,8 @@ public interface ErrorsJvm { DiagnosticFactory0 DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET = DiagnosticFactory0.create(WARNING); DiagnosticFactory0 INTERFACE_STATIC_METHOD_CALL_FROM_JAVA6_TARGET = DiagnosticFactory0.create(WARNING); + DiagnosticFactory2 INLINE_FROM_HIGHER_PLATFORM = DiagnosticFactory2.create(ERROR); + @SuppressWarnings("UnusedDeclaration") Object _initializer = new Object() { { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt index 29592421464..2e9b0c04379 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.container.useImpl import org.jetbrains.kotlin.container.useInstance import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.resolve.PlatformConfigurator +import org.jetbrains.kotlin.resolve.calls.checkers.InlineCheckerWrapper import org.jetbrains.kotlin.resolve.calls.checkers.ReifiedTypeParameterSubstitutionChecker import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.MissingDependencyClassChecker @@ -55,7 +56,8 @@ object JvmPlatformConfigurator : PlatformConfigurator( UnsupportedSyntheticCallableReferenceChecker(), SuperCallWithDefaultArgumentsChecker(), ProtectedSyntheticExtensionCallChecker, - ReifiedTypeParameterSubstitutionChecker() + ReifiedTypeParameterSubstitutionChecker(), + InlinePlatformCompatibilityChecker() ), additionalTypeCheckers = listOf( diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/library/a.kt new file mode 100644 index 00000000000..3e3e1614d32 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/library/a.kt @@ -0,0 +1,39 @@ +// JVM_TARGET: 1.8 +package a + +inline fun inlineFun(p: () -> Unit) { + p() +} + +var inlineGetter: Int + inline get() = 1 + set(varue) {} + +var inlineSetter: Int + get() = 1 + inline set(varue) {} + +var allInline: Int + inline get() = 1 + inline set(varue) {} + + + +class A { + inline fun inlineFun(p: () -> Unit) { + p() + } + + var inlineGetter: Int + inline get() = 1 + set(varue) {} + + var inlineSetter: Int + get() = 1 + inline set(varue) {} + + var allInline: Int + inline get() = 1 + inline set(varue) {} + +} \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/output.txt new file mode 100644 index 00000000000..0acfc63be5b --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/output.txt @@ -0,0 +1,37 @@ +compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:6:5: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option + inlineFun {} + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:7:5: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option + inlineGetter + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:8:5: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option + inlineGetter = 1 + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:11:5: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option + inlineSetter = 1 + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:13:5: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option + allInline + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:14:5: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option + allInline = 1 + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:17:7: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option + a.inlineFun {} + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:18:7: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option + a.inlineGetter + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:19:7: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option + a.inlineGetter = 1 + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:22:7: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option + a.inlineSetter = 1 + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:24:7: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option + a.allInline + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:25:7: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option + a.allInline = 1 + ^ +COMPILATION_ERROR \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt new file mode 100644 index 00000000000..87ad7074921 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt @@ -0,0 +1,28 @@ +package usage + +import a.* + +fun baz() { + inlineFun {} + inlineGetter + inlineGetter = 1 + + inlineSetter + inlineSetter = 1 + + allInline + allInline = 1 + + val a = A() + a.inlineFun {} + a.inlineGetter + a.inlineGetter = 1 + + a.inlineSetter + a.inlineSetter = 1 + + a.allInline + a.allInline = 1 +} + + diff --git a/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/repl/ReplCompilerJava8Test.kt b/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/repl/ReplCompilerJava8Test.kt index 8e4ccbcf0ae..7c8434f9309 100644 --- a/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/repl/ReplCompilerJava8Test.kt +++ b/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/repl/ReplCompilerJava8Test.kt @@ -83,13 +83,10 @@ class ReplCompilerJava8Test : TestCase() { val configuration = makeConfiguration().apply { put(JVMConfigurationKeys.JVM_TARGET, JvmTarget.JVM_1_6) } - try { - runTest(configuration) - Assert.fail("Should fail due to bytecode incompatibility check") - } - catch (e: CompilationException) { - Assert.assertTrue(e.message!!.contains("This compiler can only inline Java 1.6 bytecode (version 50)")) - } + + val result = runTest(configuration) + Assert.assertTrue(result is ReplCompileResult.Error) + Assert.assertTrue((result as ReplCompileResult.Error).message.contains("error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6")) } @Test @@ -98,11 +95,9 @@ class ReplCompilerJava8Test : TestCase() { val configuration = makeConfiguration() System.setProperty(KOTLIN_REPL_JVM_TARGET_PROPERTY, "1.6") try { - runTest(configuration) - Assert.fail("Should fail due to bytecode incompatibility check") - } - catch (e: CompilationException) { - Assert.assertTrue(e.message!!.contains("This compiler can only inline Java 1.6 bytecode (version 50)")) + val result = runTest(configuration) + Assert.assertTrue(result is ReplCompileResult.Error) + Assert.assertTrue((result as ReplCompileResult.Error).message.contains("error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6")) } finally { System.clearProperty(KOTLIN_REPL_JVM_TARGET_PROPERTY) diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.java index beb6fc80001..dc89eef1cdd 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.java @@ -89,15 +89,19 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir { @NotNull private File compileLibrary(@NotNull String sourcePath, @NotNull File... extraClassPath) { + return compileLibrary(sourcePath, Collections.emptyList(), extraClassPath); + } + + private File compileLibrary(@NotNull String sourcePath, List additionalOptions, @NotNull File... extraClassPath) { File destination = new File(tmpdir, sourcePath + ".jar"); - compileLibrary(new K2JVMCompiler(), sourcePath, destination, extraClassPath); + compileLibrary(new K2JVMCompiler(), sourcePath, destination, additionalOptions, extraClassPath); return destination; } private void compileLibrary( - @NotNull CLICompiler compiler, @NotNull String sourcePath, @NotNull File destination, @NotNull File... extraClassPath + @NotNull CLICompiler compiler, @NotNull String sourcePath, @NotNull File destination, List additionalOptions, @NotNull File... extraClassPath ) { - Pair output = compileKotlin(compiler, sourcePath, destination, Collections.emptyList(), extraClassPath); + Pair output = compileKotlin(compiler, sourcePath, destination, additionalOptions, extraClassPath); Assert.assertEquals(normalizeOutput(new Pair("", ExitCode.OK)), normalizeOutput(output)); } @@ -324,7 +328,7 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir { try { System.setProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY, "true"); - compileLibrary(compiler, libraryName, destination); + compileLibrary(compiler, libraryName, destination, Collections.emptyList()); } finally { System.clearProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY); @@ -629,4 +633,14 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir { Pair output = compileKotlin("source.kt", tmpdir, library1); KotlinTestUtils.assertEqualsToFile(new File(getTestDataDirectory(), "output.txt"), normalizeOutput(output)); } + + public void testWrongInlineTarget() throws Exception { + File library = compileLibrary("library", Arrays.asList("-jvm-target", "1.8")); + + Pair outputMain = compileKotlin("source.kt", tmpdir, library); + + KotlinTestUtils.assertEqualsToFile( + new File(getTestDataDirectory(), "output.txt"), normalizeOutput(outputMain) + ); + } } diff --git a/compiler/util/src/org/jetbrains/kotlin/config/JvmTarget.kt b/compiler/util/src/org/jetbrains/kotlin/config/JvmTarget.kt index cfe456ad18d..f339829bb64 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/JvmTarget.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/JvmTarget.kt @@ -17,17 +17,36 @@ package org.jetbrains.kotlin.config import org.jetbrains.kotlin.utils.DescriptionAware +import org.jetbrains.org.objectweb.asm.Opcodes enum class JvmTarget(override val description: String) : DescriptionAware { JVM_1_6("1.6"), JVM_1_8("1.8"), ; + val bytecodeVersion: Int + get() = when(this) { + JVM_1_6 -> Opcodes.V1_6 + JVM_1_8 -> Opcodes.V1_8 + } + companion object { @JvmField val DEFAULT = JVM_1_6 @JvmStatic fun fromString(string: String) = values().find { it.description == string } + + fun getDescription(bytecodeVersion: Int): String { + val platformDescription = values().find { it.bytecodeVersion == bytecodeVersion }?.description ?: + when (bytecodeVersion) { + Opcodes.V1_7 -> "1.7" + Opcodes.V1_8 + 1 -> "1.9" + else -> null + } + + return if (platformDescription != null) "JVM target $platformDescription" + else "JVM bytecode version $bytecodeVersion" + } } }