diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightMethod.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightMethod.kt index 465a4f09bea..93573a004b0 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightMethod.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightMethod.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.asJava import com.intellij.core.JavaCoreBundle import com.intellij.openapi.util.TextRange import com.intellij.psi.* +import com.intellij.psi.impl.compiled.ClsTypeElementImpl import com.intellij.psi.impl.light.LightMethod import com.intellij.psi.scope.PsiScopeProcessor import com.intellij.psi.util.* @@ -40,6 +41,10 @@ sealed class KtLightMethodImpl( override val kotlinOrigin: KtDeclaration? get() = lightMethodOrigin?.originalElement as? KtDeclaration private val lightIdentifier by lazy(LazyThreadSafetyMode.PUBLICATION) { KtLightIdentifier(this, kotlinOrigin as? KtNamedDeclaration) } + private val returnTypeElem by lazy(LazyThreadSafetyMode.PUBLICATION) { + val delegateTypeElement = clsDelegate.returnTypeElement as? ClsTypeElementImpl + delegateTypeElement?.let { ClsTypeElementImpl(this, it.canonicalText, /*ClsTypeElementImpl.VARIANCE_NONE */ 0.toChar()) } + } override fun getContainingClass(): KtLightClass = super.getContainingClass() as KtLightClass @@ -178,6 +183,12 @@ sealed class KtLightMethodImpl( override fun getDefaultValue() = clsDelegate.defaultValue } + // override getReturnType() so return type resolves to type parameters of this method not delegate's + // which is relied upon by java type inference + override fun getReturnTypeElement(): PsiTypeElement? = returnTypeElem + + override fun getReturnType() = returnTypeElement?.type + companion object Factory { fun create( delegate: PsiMethod, origin: LightMemberOrigin?, containingClass: KtLightClass diff --git a/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_6.java b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_6.java new file mode 100644 index 00000000000..7df7f5b4870 --- /dev/null +++ b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_6.java @@ -0,0 +1,7 @@ +class InferenceReturnType_1_6 { + public static void test(a.C c, a.I i, a.B b) { + a.C cc = a.Util.helper(c); + a.I ii = a.Util.helper(i); + a.B bb = a.Util.helper(b); + } +} diff --git a/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_6.kt b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_6.kt new file mode 100644 index 00000000000..3a36a0c06a4 --- /dev/null +++ b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_6.kt @@ -0,0 +1,10 @@ +@file: JvmName("Util") + +package a + +interface I + +class C : I +class B : I + +fun T.helper(): T = this \ No newline at end of file diff --git a/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_6.txt b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_6.txt new file mode 100644 index 00000000000..9b64cffb2d1 --- /dev/null +++ b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_6.txt @@ -0,0 +1 @@ +// LANGUAGE_LEVEL 1.6 \ No newline at end of file diff --git a/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_8.java b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_8.java new file mode 100644 index 00000000000..91062f8c5e0 --- /dev/null +++ b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_8.java @@ -0,0 +1,5 @@ +class InferenceReturnType_1_8 { + public static void test() { + a.A> ll = a.ValueManager.Companion.reject(); + } +} diff --git a/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_8.kt b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_8.kt new file mode 100644 index 00000000000..aae7ef2e521 --- /dev/null +++ b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_8.kt @@ -0,0 +1,11 @@ +@file: JvmName("Util") + +package a + +class A() + +class ValueManager() { + companion object { + fun reject() = null as A + } +} \ No newline at end of file diff --git a/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_8.txt b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_8.txt new file mode 100644 index 00000000000..16770180714 --- /dev/null +++ b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_8.txt @@ -0,0 +1 @@ +// LANGUAGE_LEVEL 1.8 \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/checkers/AbstractJavaAgainstKotlinCheckerTest.java b/idea/tests/org/jetbrains/kotlin/checkers/AbstractJavaAgainstKotlinCheckerTest.java index 9214faa2e7e..eda2037d9c5 100644 --- a/idea/tests/org/jetbrains/kotlin/checkers/AbstractJavaAgainstKotlinCheckerTest.java +++ b/idea/tests/org/jetbrains/kotlin/checkers/AbstractJavaAgainstKotlinCheckerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 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. @@ -22,6 +22,8 @@ import com.intellij.codeInspection.nullable.NullableStuffInspection; import com.intellij.openapi.module.Module; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.testFramework.IdeaTestUtil; import com.intellij.util.ArrayUtil; import com.siyeh.ig.bugs.StaticCallOnSubclassInspection; import com.siyeh.ig.bugs.StaticFieldReferenceOnSubclassInspection; @@ -93,10 +95,25 @@ public abstract class AbstractJavaAgainstKotlinCheckerTest extends KotlinDaemonA Module module = super.createMainModule(); String configFileText = getConfigFileText(); - if (configFileText != null && InTextDirectivesUtils.isDirectiveDefined(configFileText, "// WITH_RUNTIME")) { + if (configFileText == null) { + return module; + } + + if (InTextDirectivesUtils.isDirectiveDefined(configFileText, "// WITH_RUNTIME")) { ConfigLibraryUtil.configureKotlinRuntime(module); } + List languageLevelLines = InTextDirectivesUtils.findLinesWithPrefixesRemoved(configFileText, "// LANGUAGE_LEVEL"); + if (languageLevelLines.size() > 1) { + throw new AssertionError("Language level specified multiple times: " + languageLevelLines); + } + if (languageLevelLines.size() == 1) { + LanguageLevel level = LanguageLevel.parse(languageLevelLines.iterator().next()); + if (level != null) { + IdeaTestUtil.setModuleLanguageLevel(module, level); + } + } + return module; } diff --git a/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinBinariesCheckerTestGenerated.java b/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinBinariesCheckerTestGenerated.java index 725d59e481c..c58697c929d 100644 --- a/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinBinariesCheckerTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinBinariesCheckerTestGenerated.java @@ -77,6 +77,18 @@ public class JavaAgainstKotlinBinariesCheckerTestGenerated extends AbstractJavaA doTest(fileName); } + @TestMetadata("InferenceReturnType_1_6.kt") + public void testInferenceReturnType_1_6() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_6.kt"); + doTest(fileName); + } + + @TestMetadata("InferenceReturnType_1_8.kt") + public void testInferenceReturnType_1_8() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_8.kt"); + doTest(fileName); + } + @TestMetadata("InterfaceDefaultImpls.kt") public void testInterfaceDefaultImpls() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InterfaceDefaultImpls.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinSourceCheckerTestGenerated.java b/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinSourceCheckerTestGenerated.java index fcdd99da909..4027c9c677d 100644 --- a/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinSourceCheckerTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinSourceCheckerTestGenerated.java @@ -79,6 +79,18 @@ public class JavaAgainstKotlinSourceCheckerTestGenerated extends AbstractJavaAga doTest(fileName); } + @TestMetadata("InferenceReturnType_1_6.kt") + public void testInferenceReturnType_1_6() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_6.kt"); + doTest(fileName); + } + + @TestMetadata("InferenceReturnType_1_8.kt") + public void testInferenceReturnType_1_8() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InferenceReturnType_1_8.kt"); + doTest(fileName); + } + @TestMetadata("InterfaceDefaultImpls.kt") public void testInterfaceDefaultImpls() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/InterfaceDefaultImpls.kt");