Correct synthetic extensions for methods like "getURL"

This commit is contained in:
Valentin Kipyatkov
2015-07-10 18:55:18 +03:00
parent 22e631dda3
commit 28e9fbf9b8
5 changed files with 50 additions and 8 deletions
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.synthetic package org.jetbrains.kotlin.synthetic
import com.intellij.util.SmartList import com.intellij.util.SmartList
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
@@ -35,7 +34,8 @@ import org.jetbrains.kotlin.types.typeUtil.isBoolean
import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.* import java.beans.Introspector
import java.util.ArrayList
interface SyntheticExtensionPropertyDescriptor : PropertyDescriptor { interface SyntheticExtensionPropertyDescriptor : PropertyDescriptor {
val getMethod: FunctionDescriptor val getMethod: FunctionDescriptor
@@ -64,7 +64,7 @@ interface SyntheticExtensionPropertyDescriptor : PropertyDescriptor {
if (methodName.isSpecial()) return null if (methodName.isSpecial()) return null
val identifier = methodName.getIdentifier() val identifier = methodName.getIdentifier()
if (!identifier.startsWith(prefix)) return null if (!identifier.startsWith(prefix)) return null
val name = identifier.removePrefix(prefix).decapitalize() val name = Introspector.decapitalize(identifier.removePrefix(prefix))
if (!Name.isValidIdentifier(name)) return null if (!Name.isValidIdentifier(name)) return null
return Name.identifier(name) return Name.identifier(name)
} }
@@ -84,8 +84,16 @@ class SyntheticExtensionsScope(storageManager: StorageManager) : JetScope by Jet
private fun syntheticPropertyInClassNotCached(javaClass: JavaClassDescriptor, type: JetType, name: Name): PropertyDescriptor? { private fun syntheticPropertyInClassNotCached(javaClass: JavaClassDescriptor, type: JetType, name: Name): PropertyDescriptor? {
if (name.isSpecial()) return null if (name.isSpecial()) return null
val firstChar = name.getIdentifier()[0] val identifier = name.getIdentifier()
if (!firstChar.isJavaIdentifierStart() || firstChar.isUpperCase()) return null if (identifier.isEmpty()) return null
val firstChar = identifier[0]
if (!firstChar.isJavaIdentifierStart()) return null
if (identifier.length() > 1) {
if (firstChar.isUpperCase() != identifier[1].isUpperCase()) return null
}
else {
if (firstChar.isUpperCase()) return null
}
val memberScope = javaClass.getMemberScope(type.getArguments()) val memberScope = javaClass.getMemberScope(type.getArguments())
val getMethod = possibleGetMethodNames(name) val getMethod = possibleGetMethodNames(name)
@@ -165,7 +173,6 @@ class SyntheticExtensionsScope(storageManager: StorageManager) : JetScope by Jet
return list return list
} }
//TODO: methods like "getURL"?
//TODO: reuse code with generation? //TODO: reuse code with generation?
private fun possibleGetMethodNames(propertyName: Name): Collection<Name> { private fun possibleGetMethodNames(propertyName: Name): Collection<Name> {
@@ -0,0 +1,13 @@
// FILE: KotlinFile.kt
fun foo(javaClass: JavaClass) {
javaClass.URL = javaClass.URL + "/"
javaClass.<!UNRESOLVED_REFERENCE!>url<!>
javaClass.<!UNRESOLVED_REFERENCE!>uRL<!>
}
// FILE: JavaClass.java
public class JavaClass {
public String getURL() { return true; }
public void setURL(String value) { }
}
@@ -0,0 +1,12 @@
package
internal fun foo(/*0*/ javaClass: JavaClass): kotlin.Unit
public open class JavaClass {
public constructor JavaClass()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun getURL(): kotlin.String!
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open fun setURL(/*0*/ value: kotlin.String!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -14006,6 +14006,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
public static class SyntheticExtensions extends AbstractJetDiagnosticsTest { public static class SyntheticExtensions extends AbstractJetDiagnosticsTest {
@TestMetadata("AbbreviationName.kt")
public void testAbbreviationName() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/AbbreviationName.kt");
doTest(fileName);
}
public void testAllFilesPresentInSyntheticExtensions() throws Exception { public void testAllFilesPresentInSyntheticExtensions() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/syntheticExtensions"), Pattern.compile("^(.+)\\.kt$"), true); JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/syntheticExtensions"), Pattern.compile("^(.+)\\.kt$"), true);
} }
@@ -1,10 +1,14 @@
fun Thread.foo() { fun Thread.foo(urlConnection: java.net.URLConnection) {
<caret> with (urlConnection) {
<caret>
}
} }
// EXIST_JAVA_ONLY: { lookupString: "priority", itemText: "priority", tailText: " for Thread", typeText: "Int" } // EXIST_JAVA_ONLY: { lookupString: "priority", itemText: "priority", tailText: " for Thread", typeText: "Int" }
// EXIST_JAVA_ONLY: { lookupString: "daemon", itemText: "daemon", tailText: " for Thread", typeText: "Boolean" } // EXIST_JAVA_ONLY: { lookupString: "daemon", itemText: "daemon", tailText: " for Thread", typeText: "Boolean" }
// EXIST_JAVA_ONLY: { lookupString: "URL", itemText: "URL", tailText: " for URLConnection", typeText: "URL!" }
// ABSENT: getPriority // ABSENT: getPriority
// ABSENT: setPriority // ABSENT: setPriority
// ABSENT: isDaemon // ABSENT: isDaemon
// ABSENT: setDaemon // ABSENT: setDaemon
// ABSENT: getURL