New J2K: do not shorten class references for some Java primitive class wrappers classes

It may cause unresolved call errors

#KT-33500 fixed
This commit is contained in:
Ilya Kirillov
2019-08-26 16:47:28 +03:00
parent fd2ad89799
commit 982e7fdd86
10 changed files with 108 additions and 35 deletions
@@ -96,7 +96,8 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
return process(listOf(element), elementFilter).single() return process(listOf(element), elementFilter).single()
} }
fun process(file: KtFile, startOffset: Int, endOffset: Int) { @JvmOverloads
fun process(file: KtFile, startOffset: Int, endOffset: Int, additionalFilter: (PsiElement) -> FilterResult = { FilterResult.PROCESS }) {
val documentManager = PsiDocumentManager.getInstance(file.project) val documentManager = PsiDocumentManager.getInstance(file.project)
val document = file.viewProvider.document!! val document = file.viewProvider.document!!
if (!documentManager.isCommitted(document)) { if (!documentManager.isCommitted(document)) {
@@ -106,33 +107,36 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
val rangeMarker = document.createRangeMarker(startOffset, endOffset) val rangeMarker = document.createRangeMarker(startOffset, endOffset)
rangeMarker.isGreedyToLeft = true rangeMarker.isGreedyToLeft = true
rangeMarker.isGreedyToRight = true rangeMarker.isGreedyToRight = true
val rangeFilter = { element: PsiElement ->
if (rangeMarker.isValid) {
val range = TextRange(rangeMarker.startOffset, rangeMarker.endOffset)
val elementRange = element.textRange!!
when {
range.contains(elementRange) -> FilterResult.PROCESS
range.intersects(elementRange) -> {
// for qualified call expression allow to shorten only the part without parenthesis
val calleeExpression = ((element as? KtDotQualifiedExpression)
?.selectorExpression as? KtCallExpression)
?.calleeExpression
if (calleeExpression != null) {
val rangeWithoutParenthesis = TextRange(elementRange.startOffset, calleeExpression.textRange!!.endOffset)
if (range.contains(rangeWithoutParenthesis)) FilterResult.PROCESS else FilterResult.GO_INSIDE
} else {
FilterResult.GO_INSIDE
}
}
else -> FilterResult.SKIP
}
} else {
FilterResult.SKIP
}
}
try { try {
process(listOf(file)) { element -> process(listOf(file)) { element ->
if (rangeMarker.isValid) { minOf(rangeFilter(element), additionalFilter(element))
val range = TextRange(rangeMarker.startOffset, rangeMarker.endOffset)
val elementRange = element.textRange!!
when {
range.contains(elementRange) -> FilterResult.PROCESS
range.intersects(elementRange) -> {
// for qualified call expression allow to shorten only the part without parenthesis
val calleeExpression = ((element as? KtDotQualifiedExpression)
?.selectorExpression as? KtCallExpression)
?.calleeExpression
if (calleeExpression != null) {
val rangeWithoutParenthesis = TextRange(elementRange.startOffset, calleeExpression.textRange!!.endOffset)
if (range.contains(rangeWithoutParenthesis)) FilterResult.PROCESS else FilterResult.GO_INSIDE
} else {
FilterResult.GO_INSIDE
}
}
else -> FilterResult.SKIP
}
} else {
FilterResult.SKIP
}
} }
} finally { } finally {
rangeMarker.dispose() rangeMarker.dispose()
@@ -14,6 +14,9 @@ import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.core.util.range import org.jetbrains.kotlin.idea.core.util.range
import org.jetbrains.kotlin.idea.formatter.commitAndUnblockDocument import org.jetbrains.kotlin.idea.formatter.commitAndUnblockDocument
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.nj2k.ImportStorage
import org.jetbrains.kotlin.nj2k.asLabel import org.jetbrains.kotlin.nj2k.asLabel
import org.jetbrains.kotlin.nj2k.inference.common.BoundTypeCalculatorImpl import org.jetbrains.kotlin.nj2k.inference.common.BoundTypeCalculatorImpl
import org.jetbrains.kotlin.nj2k.inference.common.ByInfoSuperFunctionsProvider import org.jetbrains.kotlin.nj2k.inference.common.ByInfoSuperFunctionsProvider
@@ -29,6 +32,7 @@ import org.jetbrains.kotlin.nj2k.inference.nullability.NullabilityStateUpdater
import org.jetbrains.kotlin.nj2k.postProcessing.postProcessing import org.jetbrains.kotlin.nj2k.postProcessing.postProcessing
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
val formatCodeProcessing = val formatCodeProcessing =
postProcessing { file, rangeMarker, _ -> postProcessing { file, rangeMarker, _ ->
@@ -90,12 +94,19 @@ private fun KtFile.clearUndefinedLabels() {
val shortenReferencesProcessing = val shortenReferencesProcessing =
postProcessing { file, rangeMarker, _ -> postProcessing { file, rangeMarker, _ ->
val filter = filter@{ element: PsiElement ->
if (element !is KtQualifiedExpression) return@filter ShortenReferences.FilterResult.PROCESS
val fqName = element.selectorExpression?.mainReference?.resolve()?.getKotlinFqName()
?: return@filter ShortenReferences.FilterResult.PROCESS
if (ImportStorage.isImportNeeded(fqName)) ShortenReferences.FilterResult.PROCESS
else ShortenReferences.FilterResult.SKIP
}
if (rangeMarker != null) { if (rangeMarker != null) {
if (rangeMarker.isValid) { if (rangeMarker.isValid) {
ShortenReferences.DEFAULT.process(file, rangeMarker.startOffset, rangeMarker.endOffset) ShortenReferences.DEFAULT.process(file, rangeMarker.startOffset, rangeMarker.endOffset, filter)
} }
} else { } else {
ShortenReferences.DEFAULT.process(file) ShortenReferences.DEFAULT.process(file, filter)
} }
} }
@@ -73,7 +73,6 @@ object ConversionsRunner {
//Kotlin --> Kotlin conversions //Kotlin --> Kotlin conversions
+InnerClassConversion() +InnerClassConversion()
+FilterImportsConversion()
+StaticsToCompanionExtractConversion() +StaticsToCompanionExtractConversion()
+InterfaceWithFieldConversion() +InterfaceWithFieldConversion()
+ClassToObjectPromotionConversion(context) +ClassToObjectPromotionConversion(context)
@@ -84,6 +83,7 @@ object ConversionsRunner {
+LiteralConversion() +LiteralConversion()
+CollectImportsConversion(context) +CollectImportsConversion(context)
+FilterImportsConversion()
+MoveInitBlocksToTheEndConversion() +MoveInitBlocksToTheEndConversion()
+AddElementsInfoConversion(context) +AddElementsInfoConversion(context)
} }
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.nj2k package org.jetbrains.kotlin.nj2k
import com.intellij.psi.CommonClassNames
import org.jetbrains.kotlin.load.java.NULLABILITY_ANNOTATIONS import org.jetbrains.kotlin.load.java.NULLABILITY_ANNOTATIONS
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -22,9 +23,18 @@ class ImportStorage {
companion object { companion object {
fun isImportNeeded(fqName: FqName): Boolean { fun isImportNeeded(fqName: FqName): Boolean {
if (fqName in NULLABILITY_ANNOTATIONS) return false if (fqName in NULLABILITY_ANNOTATIONS) return false
if (fqName in JAVA_TYPE_WRAPPERS_WHICH_HAVE_CONFLICTS_WITH_KOTLIN_ONES) return false
return true return true
} }
private val JAVA_TYPE_WRAPPERS_WHICH_HAVE_CONFLICTS_WITH_KOTLIN_ONES = setOf(
FqName(CommonClassNames.JAVA_LANG_BYTE),
FqName(CommonClassNames.JAVA_LANG_SHORT),
FqName(CommonClassNames.JAVA_LANG_LONG),
FqName(CommonClassNames.JAVA_LANG_FLOAT),
FqName(CommonClassNames.JAVA_LANG_DOUBLE)
)
fun isImportNeeded(fqName: String): Boolean = isImportNeeded(FqName(fqName)) fun isImportNeeded(fqName: String): Boolean = isImportNeeded(FqName(fqName))
} }
} }
@@ -12,12 +12,9 @@ import org.jetbrains.kotlin.nj2k.tree.JKTreeElement
class FilterImportsConversion : RecursiveApplicableConversionBase() { class FilterImportsConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement { override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element is JKImportList) { if (element !is JKImportList) return recurse(element)
for (import in element.imports) { element.imports = element.imports.filter { import ->
if (!ImportStorage.isImportNeeded(import.name.value)) { ImportStorage.isImportNeeded(import.name.value)
element.imports -= import
}
}
} }
return recurse(element) return recurse(element)
} }
@@ -0,0 +1,10 @@
// RUNTIME_WITH_FULL_JDK
public class Test {
void m() {
Double.isFinite(2.0);
Double.isNaN(2.0);
Float.isNaN(2.0f);
Float.isInfinite(2.0f);
}
}
@@ -0,0 +1,10 @@
// RUNTIME_WITH_FULL_JDK
class Test {
internal fun m() {
java.lang.Double.isFinite(2.0)
java.lang.Double.isNaN(2.0)
java.lang.Float.isNaN(2.0f)
java.lang.Float.isInfinite(2.0f)
}
}
@@ -0,0 +1,13 @@
// RUNTIME_WITH_FULL_JDK
import java.lang.Double
import java.lang.Float
public class Test {
void m() {
Double.isFinite(2.0);
Double.isNaN(2.0);
Float.isNaN(2.0f);
Float.isInfinite(2.0f);
}
}
@@ -0,0 +1,8 @@
class Test {
internal fun m() {
java.lang.Double.isFinite(2.0)
java.lang.Double.isNaN(2.0)
java.lang.Float.isNaN(2.0f)
java.lang.Float.isInfinite(2.0f)
}
}
@@ -3472,6 +3472,16 @@ public class NewJavaToKotlinConverterSingleFileTestGenerated extends AbstractNew
runTest("nj2k/testData/newJ2k/methodCallExpression/collectionsMethods2.java"); runTest("nj2k/testData/newJ2k/methodCallExpression/collectionsMethods2.java");
} }
@TestMetadata("conflictJavaMethodCall.java")
public void testConflictJavaMethodCall() throws Exception {
runTest("nj2k/testData/newJ2k/methodCallExpression/conflictJavaMethodCall.java");
}
@TestMetadata("conflictJavaMethodCallWithExplicitImports.java")
public void testConflictJavaMethodCallWithExplicitImports() throws Exception {
runTest("nj2k/testData/newJ2k/methodCallExpression/conflictJavaMethodCallWithExplicitImports.java");
}
@TestMetadata("emptyCall.java") @TestMetadata("emptyCall.java")
public void testEmptyCall() throws Exception { public void testEmptyCall() throws Exception {
runTest("nj2k/testData/newJ2k/methodCallExpression/emptyCall.java"); runTest("nj2k/testData/newJ2k/methodCallExpression/emptyCall.java");