Review changes: revert compiler behaviour, add test, remove inner classes

This commit is contained in:
Nikolay Krasko
2019-03-11 15:45:12 +03:00
committed by Nikolay Krasko
parent 6ba134b1be
commit 213b98fefe
5 changed files with 83 additions and 55 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.load.java
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.capitalizeDecapitalize.decapitalizeSmart
import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties.getPropertyNameCandidatesBySpecialGetterName
import org.jetbrains.kotlin.util.capitalizeDecapitalize.decapitalizeSmartForCompiler
fun propertyNameByGetMethodName(methodName: Name): Name?
@@ -43,7 +44,7 @@ private fun propertyNameFromAccessorMethodName(methodName: Name, prefix: String,
}
if (!removePrefix) return methodName
val name = identifier.removePrefix(prefix).decapitalizeSmart(asciiOnly = true)
val name = identifier.removePrefix(prefix).decapitalizeSmartForCompiler(asciiOnly = true)
if (!Name.isValidIdentifier(name)) return null
return Name.identifier(name)
}
@@ -14,8 +14,28 @@
* limitations under the License.
*/
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.util.capitalizeDecapitalize
/**
* "FooBar" -> "fooBar"
* "FOOBar" -> "fooBar"
* "FOO" -> "foo"
* "FOO_BAR" -> "foO_BAR"
*/
fun String.decapitalizeSmartForCompiler(asciiOnly: Boolean = false): String {
if (isEmpty() || !isUpperCaseCharAt(0, asciiOnly)) return this
if (length == 1 || !isUpperCaseCharAt(1, asciiOnly)) {
return if (asciiOnly) decapitalizeAsciiOnly() else decapitalize()
}
val secondWordStart = (indices.firstOrNull { !isUpperCaseCharAt(it, asciiOnly) } ?: return toLowerCase(this, asciiOnly)) - 1
return toLowerCase(substring(0, secondWordStart), asciiOnly) + substring(secondWordStart)
}
/**
* "FooBar" -> "fooBar"
* "FOOBar" -> "fooBar"
@@ -24,52 +44,8 @@ package org.jetbrains.kotlin.util.capitalizeDecapitalize
* "__F_BAR" -> "fBar"
*/
fun String.decapitalizeSmart(asciiOnly: Boolean = false): String {
fun isUpperCaseCharAt(index: Int): Boolean {
val c = this[index]
return if (asciiOnly) c in 'A'..'Z' else c.isUpperCase()
}
/**
* FOOBAR -> null
* FOO_BAR -> "fooBar"
* FOO_BAR_BAZ -> "fooBarBaz"
* "__F_BAR" -> "fBar"
* "F_BAR" -> "fBar"
*/
fun decapitalizeConst(str: String): String? {
val words = str.split("_").filter { it.isNotEmpty() }
if (words.size <= 1) return null
val builder = StringBuilder()
words.forEachIndexed { index, word ->
if (index == 0) {
builder.append(word.toLowerCase())
} else {
builder.append(word.first().toUpperCase())
builder.append(word.drop(1).toLowerCase())
}
}
return builder.toString()
}
val constant = decapitalizeConst(this)
if (constant != null) return constant
if (isEmpty() || !isUpperCaseCharAt(0)) return this
if (length == 1 || !isUpperCaseCharAt(1)) {
return if (asciiOnly) decapitalizeAsciiOnly() else decapitalize()
}
fun toLowerCase(string: String) = if (asciiOnly) string.toLowerCaseAsciiOnly() else string.toLowerCase()
val secondWordStart = (indices.firstOrNull { !isUpperCaseCharAt(it) }
?: return toLowerCase(this)) - 1
return toLowerCase(substring(0, secondWordStart)) + substring(secondWordStart)
return decapitalizeWithUnderscores(this, asciiOnly)
?: decapitalizeSmartForCompiler(asciiOnly)
}
/**
@@ -78,16 +54,55 @@ fun String.decapitalizeSmart(asciiOnly: Boolean = false): String {
* "foo" -> "FOO"
*/
fun String.capitalizeFirstWord(asciiOnly: Boolean = false): String {
fun toUpperCase(string: String) = if (asciiOnly) string.toUpperCaseAsciiOnly() else string.toUpperCase()
val secondWordStart = indices.drop(1).firstOrNull { !isLowerCaseCharAt(it, asciiOnly) }
?: return toUpperCase(this, asciiOnly)
fun isLowerCaseCharAt(index: Int): Boolean {
val c = this[index]
return if (asciiOnly) c in 'a'..'z' else c.isLowerCase()
return toUpperCase(substring(0, secondWordStart), asciiOnly) + substring(secondWordStart)
}
/**
* FOOBAR -> null
* FOO_BAR -> "fooBar"
* FOO_BAR_BAZ -> "fooBarBaz"
* "__F_BAR" -> "fBar"
* "_F_BAR" -> "fBar"
* "F_BAR" -> "fBar"
*/
private fun decapitalizeWithUnderscores(str: String, asciiOnly: Boolean): String? {
val words = str.split("_").filter { it.isNotEmpty() }
if (words.size <= 1) return null
val builder = StringBuilder()
words.forEachIndexed { index, word ->
if (index == 0) {
builder.append(toLowerCase(word, asciiOnly))
} else {
builder.append(toUpperCase(word.first().toString(), asciiOnly))
builder.append(toLowerCase(word.drop(1), asciiOnly))
}
}
val secondWordStart = indices.drop(1).firstOrNull { !isLowerCaseCharAt(it) }
?: return toUpperCase(this)
return toUpperCase(substring(0, secondWordStart)) + substring(secondWordStart)
return builder.toString()
}
private fun String.isUpperCaseCharAt(index: Int, asciiOnly: Boolean): Boolean {
val c = this[index]
return if (asciiOnly) c in 'A'..'Z' else c.isUpperCase()
}
private fun String.isLowerCaseCharAt(index: Int, asciiOnly: Boolean): Boolean {
val c = this[index]
return if (asciiOnly) c in 'a'..'z' else c.isLowerCase()
}
private fun toLowerCase(string: String, asciiOnly: Boolean): String {
return if (asciiOnly) string.toLowerCaseAsciiOnly() else string.toLowerCase()
}
private fun toUpperCase(string: String, asciiOnly: Boolean): String {
return if (asciiOnly) string.toUpperCaseAsciiOnly() else string.toUpperCase()
}
fun String.capitalizeAsciiOnly(): String {
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.util.capitalizeDecapitalize.decapitalizeSmart
import org.jetbrains.kotlin.util.capitalizeDecapitalize.decapitalizeSmartForCompiler
import java.util.*
data class ReferenceVariants(val imported: Collection<DeclarationDescriptor>, val notImportedExtensions: Collection<CallableDescriptor>)
@@ -121,7 +122,7 @@ class ReferenceVariantsCollector(
val getOrSetPrefix = GET_SET_PREFIXES.firstOrNull { prefix.startsWith(it) }
val additionalPropertyNameFilter: ((String) -> Boolean)? = getOrSetPrefix
?.let { prefixMatcher.cloneWithPrefix(prefix.removePrefix(getOrSetPrefix).decapitalizeSmart()).asStringNameFilter() }
?.let { prefixMatcher.cloneWithPrefix(prefix.removePrefix(getOrSetPrefix).decapitalizeSmartForCompiler()).asStringNameFilter() }
val shadowedDeclarationsFilter = if (runtimeReceiver != null)
ShadowedDeclarationsFilter(bindingContext, resolutionFacade, nameExpression, runtimeReceiver)
@@ -0,0 +1,9 @@
fun a() {
val SOME_CONSTANT = 1
<selection>SOME_CONSTANT</selection>
}
/*
constant
i
someConstant
*/
@@ -38,6 +38,8 @@ class KotlinNameSuggesterTest : KotlinLightCodeInsightFixtureTestCase() {
fun testNameReferenceExpression() = doTest()
fun testNameReferenceExpressionForConstants() = doTest()
fun testNameString() = doTest()
fun testAnonymousObject() = doTest()