mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-216155: inspection that warns if API marked with @ScheduledForRemoval annotation must already be removed.
GitOrigin-RevId: bb9cc3c842e6110d801f718717665498a077e3a3
This commit is contained in:
committed by
intellij-monorepo-bot
parent
8ca5faf856
commit
9b498304a6
@@ -31,6 +31,10 @@
|
||||
groupBundle="com.intellij.jvm.analysis.JvmAnalysisBundle" bundle="com.intellij.jvm.analysis.JvmAnalysisBundle"
|
||||
groupKey="jvm.inspections.group.name" key="jvm.inspections.missing.deprecated.annotation.on.scheduled.for.removal.api.display.name"
|
||||
implementationClass="com.intellij.codeInspection.MissingDeprecatedAnnotationOnScheduledForRemovalApiInspection"/>
|
||||
<localInspection language="UAST" enabledByDefault="true" level="ERROR" shortName="MustAlreadyBeRemovedApi"
|
||||
groupBundle="com.intellij.jvm.analysis.JvmAnalysisBundle" bundle="com.intellij.jvm.analysis.JvmAnalysisBundle"
|
||||
groupKey="jvm.inspections.group.name" key="jvm.inspections.must.already.be.removed.api.display.name"
|
||||
implementationClass="com.intellij.codeInspection.MustAlreadyBeRemovedApiInspection"/>
|
||||
</extensions>
|
||||
<extensions defaultExtensionNs="com.intellij.codeInsight">
|
||||
<blockingMethodChecker implementation="com.intellij.codeInspection.blockingCallsDetection.ThrowsTypeBlockingMethodChecker"/>
|
||||
|
||||
@@ -10,6 +10,9 @@ jvm.inspections.scheduled.for.removal.description.with.version=''{0}'' is schedu
|
||||
jvm.inspections.missing.deprecated.annotation.on.scheduled.for.removal.api.display.name=Missing '@Deprecated' annotation on scheduled for removal API
|
||||
jvm.inspections.missing.deprecated.annotation.on.scheduled.for.removal.api.description=Scheduled for removal API must also be marked with '@Deprecated' annotation
|
||||
jvm.inspections.missing.deprecated.annotation.on.scheduled.for.removal.api.quick.fix=Add '@Deprecated' annotation
|
||||
jvm.inspections.must.already.be.removed.api.display.name=API must already be removed
|
||||
jvm.inspections.must.already.be.removed.api.earlier.version.description=API must have been removed in version {0} but the current version is {1}
|
||||
jvm.inspections.must.already.be.removed.api.current.version.description=API must be removed in the current version {0}
|
||||
jvm.inspections.blocking.method.problem.descriptor=Inappropriate blocking method call
|
||||
jvm.inspections.blocking.method.display.name=Inappropriate thread-blocking method call
|
||||
jvm.inspections.blocking.method.annotation.blocking=Blocking Annotations
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports any declarations of classes, fields, or methods marked with <b>@org.jetbrains.annotations.ApiStatus.ScheduledForRemoval</b>
|
||||
annotation that must already be removed. Specified scheduled removal version is compared with the current version that you may set below.
|
||||
Versions are dot-separated strings with possibly "alpha", "beta", "eap" classifiers, like "1.0", "2.3.1", "2018.1", "7.5-snapshot",
|
||||
"3.0-eap". Versions comparison is intuitive: 1.0 < 2.0, 1.0-eap < 1.0, 2.3-snapshot < 2.3 and so on.
|
||||
For detailed comparison logic refer to implementation of <a
|
||||
href="https://github.com/JetBrains/intellij-community/blob/master/platform/util-rt/src/com/intellij/util/text/VersionComparatorUtil.java">VersionComparatorUtil</a>.
|
||||
</body>
|
||||
</html>
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.codeInspection
|
||||
|
||||
import com.intellij.analysis.JvmAnalysisBundle
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.uast.UastVisitorAdapter
|
||||
import com.intellij.ui.components.JBTextField
|
||||
import com.intellij.ui.components.fields.valueEditors.TextFieldValueEditor
|
||||
import com.intellij.util.text.VersionComparatorUtil
|
||||
import com.intellij.util.ui.FormBuilder
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.uast.UAnnotated
|
||||
import org.jetbrains.uast.UDeclaration
|
||||
import org.jetbrains.uast.evaluateString
|
||||
import org.jetbrains.uast.sourcePsiElement
|
||||
import org.jetbrains.uast.visitor.AbstractUastNonRecursiveVisitor
|
||||
import java.awt.BorderLayout
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JPanel
|
||||
|
||||
/**
|
||||
* Reports declarations (classes, methods, fields) marked with [ApiStatus.ScheduledForRemoval] annotation
|
||||
* that must already be removed. [ApiStatus.ScheduledForRemoval.inVersion] value is compared with "current" version.
|
||||
*/
|
||||
class MustAlreadyBeRemovedApiInspection : LocalInspectionTool() {
|
||||
|
||||
private companion object {
|
||||
private val SCHEDULED_FOR_REMOVAL_ANNOTATION_NAME = ApiStatus.ScheduledForRemoval::class.java.canonicalName
|
||||
}
|
||||
|
||||
var currentVersion: String = ""
|
||||
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
||||
if (currentVersion.isEmpty()) return PsiElementVisitor.EMPTY_VISITOR
|
||||
return UastVisitorAdapter(MustAlreadyBeRemovedApiVisitor(holder, currentVersion), true)
|
||||
}
|
||||
|
||||
private class MustAlreadyBeRemovedApiVisitor(
|
||||
private val problemsHolder: ProblemsHolder,
|
||||
private val currentVersion: String
|
||||
) : AbstractUastNonRecursiveVisitor() {
|
||||
override fun visitDeclaration(node: UDeclaration): Boolean {
|
||||
val versionOfScheduledRemoval = getVersionOfScheduledRemoval(node)
|
||||
if (versionOfScheduledRemoval != null && VersionComparatorUtil.compare(currentVersion, versionOfScheduledRemoval) >= 0) {
|
||||
val message = if (currentVersion == versionOfScheduledRemoval) {
|
||||
JvmAnalysisBundle.message(
|
||||
"jvm.inspections.must.already.be.removed.api.current.version.description",
|
||||
currentVersion
|
||||
)
|
||||
}
|
||||
else {
|
||||
JvmAnalysisBundle.message(
|
||||
"jvm.inspections.must.already.be.removed.api.earlier.version.description",
|
||||
versionOfScheduledRemoval,
|
||||
currentVersion
|
||||
)
|
||||
}
|
||||
|
||||
val identifierPsi = node.uastAnchor.sourcePsiElement ?: return true
|
||||
problemsHolder.registerProblem(identifierPsi, message, ProblemHighlightType.GENERIC_ERROR_OR_WARNING)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun getVersionOfScheduledRemoval(annotated: UAnnotated): String? {
|
||||
val annotation = annotated.findAnnotation(SCHEDULED_FOR_REMOVAL_ANNOTATION_NAME) ?: return null
|
||||
return annotation.findDeclaredAttributeValue("inVersion")?.evaluateString()
|
||||
}
|
||||
}
|
||||
|
||||
override fun createOptionsPanel(): JComponent? {
|
||||
val versionField = VersionField("Version", "")
|
||||
versionField.version = currentVersion
|
||||
versionField.versionEditor.addListener { version ->
|
||||
currentVersion = version
|
||||
}
|
||||
|
||||
val formBuilder = FormBuilder.createFormBuilder()
|
||||
.addLabeledComponent("Current version", versionField)
|
||||
|
||||
val container = JPanel(BorderLayout())
|
||||
container.add(formBuilder.panel, BorderLayout.NORTH)
|
||||
return container
|
||||
}
|
||||
|
||||
private class VersionField(valueName: String, defaultValue: String) : JBTextField() {
|
||||
|
||||
val versionEditor: VersionEditor = VersionEditor(this, valueName, defaultValue)
|
||||
|
||||
var version: String
|
||||
get() = versionEditor.value
|
||||
set(value) {
|
||||
versionEditor.value = value
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class VersionEditor(textField: JBTextField, valueName: String, defaultValue: String)
|
||||
: TextFieldValueEditor<String>(textField, valueName, defaultValue) {
|
||||
|
||||
override fun parseValue(text: String?): String = text ?: ""
|
||||
override fun valueToString(value: String) = value
|
||||
|
||||
override fun isValid(value: String): Boolean = true
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package test;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "2.0")
|
||||
@Deprecated
|
||||
class <error descr="API must have been removed in version 2.0 but the current version is 3.0">Warnings</error> {
|
||||
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "2.0")
|
||||
@Deprecated
|
||||
public String <error descr="API must have been removed in version 2.0 but the current version is 3.0">field</error>;
|
||||
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "2.0")
|
||||
@Deprecated
|
||||
public void <error descr="API must have been removed in version 2.0 but the current version is 3.0">method</error>() {
|
||||
}
|
||||
}
|
||||
|
||||
//No warnings should be produced.
|
||||
|
||||
@Deprecated
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "5.0")
|
||||
class NoWarnings {
|
||||
|
||||
@Deprecated
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "5.0")
|
||||
public String field;
|
||||
|
||||
@Deprecated
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "5.0")
|
||||
public void method() {
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.intellij.codeInspection.tests.java
|
||||
|
||||
import com.intellij.codeInspection.tests.MustAlreadyBeRemovedApiInspectionTestBase
|
||||
import com.intellij.jvm.analysis.JvmAnalysisTestsUtil
|
||||
import com.intellij.testFramework.TestDataPath
|
||||
|
||||
@TestDataPath("\$CONTENT_ROOT/testData/codeInspection/mustAlreadyBeRemovedApi")
|
||||
class JavaMustAlreadyBeRemovedApiInspectionTest : MustAlreadyBeRemovedApiInspectionTestBase() {
|
||||
|
||||
override fun getTestDataPath() = JvmAnalysisTestsUtil.TEST_DATA_PROJECT_RELATIVE_BASE_PATH + "/codeInspection/mustAlreadyBeRemovedApi"
|
||||
|
||||
fun `test APIs must have been removed`() {
|
||||
myFixture.testHighlighting("outdatedApi.java")
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package test
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "2.0")
|
||||
@Deprecated("")
|
||||
class <error descr="API must have been removed in version 2.0 but the current version is 3.0">Warnings</error> {
|
||||
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "2.0")
|
||||
@Deprecated("")
|
||||
var <error descr="API must have been removed in version 2.0 but the current version is 3.0">field</error>: String? = null
|
||||
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "2.0")
|
||||
@Deprecated("")
|
||||
fun <error descr="API must have been removed in version 2.0 but the current version is 3.0">method</error>() {
|
||||
}
|
||||
}
|
||||
|
||||
//No warnings should be produced.
|
||||
|
||||
@Deprecated("")
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "5.0")
|
||||
class NoWarnings {
|
||||
|
||||
@Deprecated("")
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "5.0")
|
||||
var field: String? = null
|
||||
|
||||
@Deprecated("")
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "5.0")
|
||||
fun method() {
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.intellij.codeInspection
|
||||
|
||||
import com.intellij.codeInspection.tests.MustAlreadyBeRemovedApiInspectionTestBase
|
||||
import com.intellij.jvm.analysis.JvmAnalysisKtTestsUtil
|
||||
import com.intellij.testFramework.TestDataPath
|
||||
|
||||
@TestDataPath("\$CONTENT_ROOT/testData/codeInspection/mustAlreadyBeRemovedApi")
|
||||
class KotlinMustAlreadyBeRemovedApiInspectionTest : MustAlreadyBeRemovedApiInspectionTestBase() {
|
||||
|
||||
override fun getBasePath() = JvmAnalysisKtTestsUtil.TEST_DATA_PROJECT_RELATIVE_BASE_PATH + "/codeInspection/mustAlreadyBeRemovedApi"
|
||||
|
||||
fun `test APIs must have been removed`() {
|
||||
myFixture.testHighlighting("outdatedApi.kt")
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.intellij.codeInspection.tests
|
||||
|
||||
import com.intellij.codeInspection.MustAlreadyBeRemovedApiInspection
|
||||
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase
|
||||
import com.intellij.util.PathUtil
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
abstract class MustAlreadyBeRemovedApiInspectionTestBase : JavaCodeInsightFixtureTestCase() {
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
val inspection = MustAlreadyBeRemovedApiInspection()
|
||||
inspection.currentVersion = "3.0"
|
||||
myFixture.enableInspections(inspection)
|
||||
}
|
||||
|
||||
override fun tuneFixture(moduleBuilder: JavaModuleFixtureBuilder<*>) {
|
||||
moduleBuilder.addLibrary("util", PathUtil.getJarPathForClass(ApiStatus.ScheduledForRemoval::class.java))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user