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()
}
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 document = file.viewProvider.document!!
if (!documentManager.isCommitted(document)) {
@@ -106,33 +107,36 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
val rangeMarker = document.createRangeMarker(startOffset, endOffset)
rangeMarker.isGreedyToLeft = 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 {
process(listOf(file)) { element ->
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
}
minOf(rangeFilter(element), additionalFilter(element))
}
} finally {
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.util.range
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.inference.common.BoundTypeCalculatorImpl
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.psi.*
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
val formatCodeProcessing =
postProcessing { file, rangeMarker, _ ->
@@ -90,12 +94,19 @@ private fun KtFile.clearUndefinedLabels() {
val shortenReferencesProcessing =
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.isValid) {
ShortenReferences.DEFAULT.process(file, rangeMarker.startOffset, rangeMarker.endOffset)
ShortenReferences.DEFAULT.process(file, rangeMarker.startOffset, rangeMarker.endOffset, filter)
}
} else {
ShortenReferences.DEFAULT.process(file)
ShortenReferences.DEFAULT.process(file, filter)
}
}
@@ -73,7 +73,6 @@ object ConversionsRunner {
//Kotlin --> Kotlin conversions
+InnerClassConversion()
+FilterImportsConversion()
+StaticsToCompanionExtractConversion()
+InterfaceWithFieldConversion()
+ClassToObjectPromotionConversion(context)
@@ -84,6 +83,7 @@ object ConversionsRunner {
+LiteralConversion()
+CollectImportsConversion(context)
+FilterImportsConversion()
+MoveInitBlocksToTheEndConversion()
+AddElementsInfoConversion(context)
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.nj2k
import com.intellij.psi.CommonClassNames
import org.jetbrains.kotlin.load.java.NULLABILITY_ANNOTATIONS
import org.jetbrains.kotlin.name.FqName
@@ -22,9 +23,18 @@ class ImportStorage {
companion object {
fun isImportNeeded(fqName: FqName): Boolean {
if (fqName in NULLABILITY_ANNOTATIONS) return false
if (fqName in JAVA_TYPE_WRAPPERS_WHICH_HAVE_CONFLICTS_WITH_KOTLIN_ONES) return false
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))
}
}
@@ -12,12 +12,9 @@ import org.jetbrains.kotlin.nj2k.tree.JKTreeElement
class FilterImportsConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element is JKImportList) {
for (import in element.imports) {
if (!ImportStorage.isImportNeeded(import.name.value)) {
element.imports -= import
}
}
if (element !is JKImportList) return recurse(element)
element.imports = element.imports.filter { import ->
ImportStorage.isImportNeeded(import.name.value)
}
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");
}
@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")
public void testEmptyCall() throws Exception {
runTest("nj2k/testData/newJ2k/methodCallExpression/emptyCall.java");