Use LanguageFeatureSettings instead of custom option for bound callable references

This commit is contained in:
Alexander Udalov
2016-05-27 19:16:08 +03:00
parent 7240a8df6c
commit d90b40c661
8 changed files with 67 additions and 9 deletions
@@ -18,12 +18,13 @@ package org.jetbrains.kotlin.config
import org.jetbrains.kotlin.config.LanguageVersion.KOTLIN_1_1
enum class LanguageFeature(val sinceVersion: LanguageVersion) {
// Note: names of these entries are also used in diagnostic tests
TypeAliases(KOTLIN_1_1),
BoundCallableReferences(KOTLIN_1_1),
LocalDelegatedProperties(KOTLIN_1_1),
TopLevelSealedInheritance(KOTLIN_1_1);
TopLevelSealedInheritance(KOTLIN_1_1),
;
companion object {
@JvmStatic
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.types.expressions
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.ReflectionTypes
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageFeatureSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
@@ -40,9 +42,6 @@ import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
import javax.inject.Inject
// TODO: use a language level option
val BOUND_REFERENCES_ENABLED by lazy { System.getProperty("kotlin.lang.enable.bound.references") == "true" }
sealed class DoubleColonLHS(val type: KotlinType) {
class Expression(val typeInfo: KotlinTypeInfo) : DoubleColonLHS(typeInfo.type!!)
@@ -58,7 +57,8 @@ class DoubleColonExpressionResolver(
val qualifiedExpressionResolver: QualifiedExpressionResolver,
val dataFlowAnalyzer: DataFlowAnalyzer,
val reflectionTypes: ReflectionTypes,
val typeResolver: TypeResolver
val typeResolver: TypeResolver,
val languageFeatureSettings: LanguageFeatureSettings
) {
private lateinit var expressionTypingServices: ExpressionTypingServices
@@ -120,13 +120,20 @@ class DoubleColonExpressionResolver(
}
}
private fun shouldTryResolveLHSAsExpression(expression: KtDoubleColonExpression): Boolean {
// TODO: improve diagnostic when bound callable references are disabled
if (!languageFeatureSettings.supportsFeature(LanguageFeature.BoundCallableReferences)) return false
val lhs = expression.receiverExpression ?: return false
return lhs.canBeConsideredProperExpression() && !expression.hasQuestionMarks /* TODO: test this */
}
private fun resolveDoubleColonLHS(
expression: KtExpression, doubleColonExpression: KtDoubleColonExpression, c: ExpressionTypingContext
): DoubleColonLHS? {
// First, try resolving the LHS as expression, if possible
if (BOUND_REFERENCES_ENABLED && expression.canBeConsideredProperExpression() &&
!doubleColonExpression.hasQuestionMarks /* TODO: test this */) {
if (shouldTryResolveLHSAsExpression(doubleColonExpression)) {
val traceForExpr = TemporaryTraceAndCache.create(c, "resolve '::' LHS as expression", expression)
val contextForExpr = c.replaceTraceAndCache(traceForExpr)
val typeInfo = expressionTypingServices.getTypeInfo(expression, contextForExpr)
@@ -15,6 +15,6 @@ data class User(val surname: String)
fun foo() {
bar<String> {
<!UNUSED_EXPRESSION!>User::surname<!>
<!UNUSED_EXPRESSION!><!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>User<!>::<!OVERLOAD_RESOLUTION_AMBIGUITY!>surname<!><!>
}
}
@@ -0,0 +1,11 @@
// !LANGUAGE: -BoundCallableReferences
// !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS
import kotlin.reflect.KClass
val <T : Any> KClass<T>.java: Class<T> get() = null!!
val <T : Any> KClass<T>.javaObjectType: Class<T>
get() {
return java.lang.Class::class.java as Class<T>
}
@@ -0,0 +1,4 @@
package
public val </*0*/ T : kotlin.Any> kotlin.reflect.KClass<T>.java: java.lang.Class<T>
public val </*0*/ T : kotlin.Any> kotlin.reflect.KClass<T>.javaObjectType: java.lang.Class<T>
@@ -0,0 +1,10 @@
// !LANGUAGE: -BoundCallableReferences
import kotlin.reflect.KClass
val <T : Any> KClass<T>.java: Class<T> get() = null!!
val <T : Any> KClass<T>.foo: Any?
get() {
return java.lang.Integer::hashCode
}
@@ -0,0 +1,4 @@
package
public val </*0*/ T : kotlin.Any> kotlin.reflect.KClass<T>.foo: kotlin.Any?
public val </*0*/ T : kotlin.Any> kotlin.reflect.KClass<T>.java: java.lang.Class<T>
@@ -18383,6 +18383,27 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/noTopLevelSealedInheritance.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NoBoundCallableReferences extends AbstractDiagnosticsTest {
public void testAllFilesPresentInNoBoundCallableReferences() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("qualifiedJavaClassLiteralInKClassExtension.kt")
public void testQualifiedJavaClassLiteralInKClassExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences/qualifiedJavaClassLiteralInKClassExtension.kt");
doTest(fileName);
}
@TestMetadata("qualifiedJavaClassReferenceInKClassExtension.kt")
public void testQualifiedJavaClassReferenceInKClassExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences/qualifiedJavaClassReferenceInKClassExtension.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/diagnostics/tests/substitutions")