KT-39869 Add inspection for FQN usages of kotlin.browser package

- `kotlin.dom` does not need this because it contains only extensions
- Add test for launching whole project fix; mute it because currently it
does not pass
  - The test fails because in tests `RefJavaManager` tries to create
  `RefJavaFileImpl` for .kt files. It will try to use UAST, but it
  does not work for JS files. In production this is disabled, so no
  problems occur
This commit is contained in:
Roman Golyshev
2020-07-04 21:07:30 +03:00
committed by Roman Golyshev
parent 91fa5d38b3
commit 5cf6b860a6
7 changed files with 110 additions and 1 deletions
@@ -6,14 +6,23 @@
package org.jetbrains.kotlin.idea.inspections.migration
import com.intellij.codeInspection.*
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.common.serialization.findPackage
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.codeInsight.shorten.performDelayedRefactoringRequests
import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
internal class ObsoleteKotlinJsPackagesInspection : ObsoleteCodeMigrationInspection() {
override val fromVersion: LanguageVersion = LanguageVersion.KOTLIN_1_3
override val toVersion: LanguageVersion = LanguageVersion.KOTLIN_1_4
override val problemReporters: List<ObsoleteCodeProblemReporter> = listOf(
KotlinBrowserFullyQualifiedUsageReporter,
KotlinBrowserImportUsageReporter,
KotlinDomImportUsageReporter
)
@@ -25,6 +34,7 @@ private object ObsoleteKotlinJsPackagesUsagesInWholeProjectFix : ObsoleteCodeInW
}
private const val KOTLIN_BROWSER_PACKAGE = "kotlin.browser"
private const val KOTLINX_BROWSER_PACKAGE = "kotlinx.browser"
private const val KOTLIN_DOM_PACKAGE = "kotlin.dom"
private class ObsoleteKotlinBrowserUsageFix(delegate: ObsoleteCodeFix) : ObsoleteCodeFixDelegateQuickFix(delegate) {
@@ -35,9 +45,55 @@ private class ObsoleteKotlinDomUsageFix(delegate: ObsoleteCodeFix) : ObsoleteCod
override fun getFamilyName(): String = KotlinBundle.message("obsolete.package.usage.fix.family.name", KOTLIN_DOM_PACKAGE)
}
/**
* We have such inspection only for 'kotlin.browser' package; it is because 'kotlin.dom' package has only extension functions. Such
* functions cannot be used with fully qualified name.
*/
private object KotlinBrowserFullyQualifiedUsageReporter : ObsoleteCodeProblemReporter {
override fun report(holder: ProblemsHolder, isOnTheFly: Boolean, simpleNameExpression: KtSimpleNameExpression): Boolean {
val fullyQualifiedExpression = simpleNameExpression.parent as? KtDotQualifiedExpression ?: return false
val kotlinBrowserQualifier = fullyQualifiedExpression.receiverExpression as? KtDotQualifiedExpression ?: return false
if (kotlinBrowserQualifier.text != KOTLIN_BROWSER_PACKAGE) return false
if (!resolvesToKotlinBrowserPackage(simpleNameExpression)) return false
holder.registerProblem(
kotlinBrowserQualifier,
KotlinBundle.message("package.usages.are.obsolete.since.1.4", KOTLIN_DOM_PACKAGE),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
*fixesWithWholeProject(
isOnTheFly,
fix = ObsoleteKotlinBrowserUsageFix(KotlinBrowserFullyQualifiedUsageFix),
wholeProjectFix = ObsoleteKotlinJsPackagesUsagesInWholeProjectFix
)
)
return true
}
private fun resolvesToKotlinBrowserPackage(simpleNameExpression: KtSimpleNameExpression): Boolean {
val referencedDescriptor =
simpleNameExpression.resolveMainReferenceToDescriptors().singleOrNull() as? CallableDescriptor ?: return false
return referencedDescriptor.findPackage().fqName.asString() == KOTLIN_BROWSER_PACKAGE
}
object KotlinBrowserFullyQualifiedUsageFix : ObsoleteCodeFix {
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val oldQualifier = descriptor.psiElement as? KtDotQualifiedExpression ?: return
val newQualifier = KtPsiFactory(oldQualifier).createExpression(KOTLINX_BROWSER_PACKAGE)
oldQualifier.replace(newQualifier)
performDelayedRefactoringRequests(project)
}
}
}
private object KotlinBrowserImportUsageReporter : ObsoleteImportsUsageReporter() {
override val textMarker: String = "browser"
override val packageBindings: Map<String, String> = mapOf(KOTLIN_BROWSER_PACKAGE to "kotlinx.browser")
override val packageBindings: Map<String, String> = mapOf(KOTLIN_BROWSER_PACKAGE to KOTLINX_BROWSER_PACKAGE)
override val wholeProjectFix: LocalQuickFix = ObsoleteKotlinJsPackagesUsagesInWholeProjectFix
override fun problemMessage(): String = KotlinBundle.message("package.usages.are.obsolete.since.1.4", KOTLIN_BROWSER_PACKAGE)
@@ -0,0 +1,10 @@
// "Fix 'kotlin.browser' package usage" "true"
// JS
package test
fun use(a: Any) {}
fun usage() {
use(kotlin.<caret>browser.localStorage.toString())
}
@@ -0,0 +1,10 @@
// "Fix 'kotlin.browser' package usage" "true"
// JS
package test
fun use(a: Any) {}
fun usage() {
use(kotlinx.browser.localStorage.toString())
}
@@ -0,0 +1,11 @@
// "Fix 'kotlin.dom' and 'kotlin.browser' packages usages in the project" "true"
// JS
package test
import kotlin.<caret>browser.localStorage
import kotlin.dom.addClass
fun usage() {
kotlin.browser.document.toString()
}
@@ -0,0 +1,11 @@
// "Fix 'kotlin.dom' and 'kotlin.browser' packages usages in the project" "true"
// JS
package test
import kotlinx.browser.localStorage
import kotlinx.dom.addClass
fun usage() {
kotlinx.browser.document.toString()
}
@@ -9898,6 +9898,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/quickfix/obsoleteKotlinJsPackages"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true);
}
@TestMetadata("kotlinBrowserFullyQualifiedProperty.kt")
public void testKotlinBrowserFullyQualifiedProperty() throws Exception {
runTest("idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserFullyQualifiedProperty.kt");
}
@TestMetadata("kotlinBrowserPropertyImport.kt")
public void testKotlinBrowserPropertyImport() throws Exception {
runTest("idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserPropertyImport.kt");
@@ -9908,6 +9913,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserStarImport.kt");
}
@TestMetadata("kotlinDomAndBrowserImport.kt")
public void testKotlinDomAndBrowserImport() throws Exception {
runTest("idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomAndBrowserImport.kt");
}
@TestMetadata("kotlinDomPropertyImport.kt")
public void testKotlinDomPropertyImport() throws Exception {
runTest("idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomPropertyImport.kt");
+1
View File
@@ -45,6 +45,7 @@ org.jetbrains.kotlin.idea.quickfix.QuickFixMultiModuleTestGenerated.CreateActual
org.jetbrains.kotlin.idea.quickfix.QuickFixTestGenerated.CreateFromUsage.CreateClass.CallExpression.testCallInWhenEntry, KT-35728,,
org.jetbrains.kotlin.idea.quickfix.QuickFixTestGenerated.Libraries.testJunit, ERROR: Couldn't find the following libraries,,
org.jetbrains.kotlin.idea.quickfix.QuickFixTestGenerated.Libraries.testTestNG, ERROR: Couldn't find the following libraries,,
org.jetbrains.kotlin.idea.quickfix.QuickFixTestGenerated.ObsoleteKotlinJsPackages.testKotlinDomAndBrowserImport, Always red because UAST does not work with JS,,
org.jetbrains.kotlin.idea.refactoring.move.MultiModuleMoveTestGenerated.testMoveFromJvmModuleToJsModule_MoveFromJvmModuleToJsModule, KT-34106,,
org.jetbrains.kotlin.idea.refactoring.move.MultiModuleMoveTestGenerated.testMoveJdkDependentToJsModule_MoveJdkDependentToJsModule, KT-34106,,
org.jetbrains.kotlin.idea.resolve.PartialBodyResolveTestGenerated.testSmartCastInTheSameStatement, KT-35922,,
1 Test key Issue State (optional: MUTE or FAIL) Status (optional: FLAKY)
45 org.jetbrains.kotlin.idea.quickfix.QuickFixTestGenerated.CreateFromUsage.CreateClass.CallExpression.testCallInWhenEntry KT-35728
46 org.jetbrains.kotlin.idea.quickfix.QuickFixTestGenerated.Libraries.testJunit ERROR: Couldn't find the following libraries
47 org.jetbrains.kotlin.idea.quickfix.QuickFixTestGenerated.Libraries.testTestNG ERROR: Couldn't find the following libraries
48 org.jetbrains.kotlin.idea.quickfix.QuickFixTestGenerated.ObsoleteKotlinJsPackages.testKotlinDomAndBrowserImport Always red because UAST does not work with JS
49 org.jetbrains.kotlin.idea.refactoring.move.MultiModuleMoveTestGenerated.testMoveFromJvmModuleToJsModule_MoveFromJvmModuleToJsModule KT-34106
50 org.jetbrains.kotlin.idea.refactoring.move.MultiModuleMoveTestGenerated.testMoveJdkDependentToJsModule_MoveJdkDependentToJsModule KT-34106
51 org.jetbrains.kotlin.idea.resolve.PartialBodyResolveTestGenerated.testSmartCastInTheSameStatement KT-35922