ImplicitSubclassProvider API updates and ImplicitSubclassInspection descriptions improvements

This commit is contained in:
Nicolay Mitropolsky
2017-04-25 13:53:46 +03:00
committed by nickl
parent 0026a6cd63
commit 3ce45245ee
7 changed files with 34 additions and 41 deletions
@@ -23,7 +23,7 @@ public class ImplementedAtRuntimeConditionImpl extends ImplementedAtRuntimeCondi
@Override
public boolean isImplementedAtRuntime(@NotNull PsiClass psiClass) {
for (ImplicitSubclassProvider provider : ImplicitSubclassProvider.Companion.getEP_NAME().getExtensions()) {
SubclassingInfo info = provider.getSubclassingInfo(psiClass);
ImplicitSubclassProvider.SubclassingInfo info = provider.getSubclassingInfo(psiClass);
if (info != null && !info.isAbstract()) {
return true;
}
@@ -39,7 +39,7 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
val methodsToOverride = aClass.methods.mapNotNull {
method ->
subclassInfos
.mapNotNull { it.getOverridingInfo(method)?.description }
.mapNotNull { it.methodsInfo?.get(method)?.description }
.firstOrNull()?.let { description ->
method to description
}
@@ -55,8 +55,8 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
if (method.isFinal || method.isStatic || method.hasModifierProperty(PsiModifier.PRIVATE)) {
methodsToAttachToClassFix?.add(smartPointerManager.createSmartPsiElementPointer(method, method.containingFile))
val methodFixes = if (method.modifierList.isWritable)
arrayOf<LocalQuickFix>(FixSubclassing(method, method.name))
val methodFixes = if (canApplyFix(method))
arrayOf<LocalQuickFix>(MakeExtendableFix(method, method.name))
else
emptyArray()
@@ -76,7 +76,7 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
problems.add(manager.createProblemDescriptor(
it, classReasonToBeSubclassed ?: InspectionsBundle.message("inspection.implicit.subclass.display.forClass", aClass.name),
isOnTheFly,
arrayOf<LocalQuickFix>(FixSubclassing(aClass, aClass.name ?: "class", methodsToAttachToClassFix ?: emptyList())),
arrayOf<LocalQuickFix>(MakeExtendableFix(aClass, aClass.name ?: "class", methodsToAttachToClassFix ?: emptyList())),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING)
)
}
@@ -86,7 +86,7 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
return problems.toTypedArray()
}
private fun canApplyFix(aClass: UClass) = aClass.modifierList?.isWritable ?: false
private fun canApplyFix(aClass: UDeclaration) = aClass.modifierList?.isWritable ?: false
private fun problemTargets(declaration: UDeclaration, highlightableModifiersSet: Set<String>): List<PsiElement> {
val modifiersElements = declaration.modifierList?.let {
@@ -105,9 +105,9 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
private val classHighlightableModifiersSet = setOf(PsiModifier.FINAL, PsiModifier.PRIVATE)
private class FixSubclassing(uDeclaration: UDeclaration,
hintTargetName: String,
val siblings: List<SmartPsiElementPointer<UDeclaration>> = emptyList())
private class MakeExtendableFix(uDeclaration: UDeclaration,
hintTargetName: String,
val siblings: List<SmartPsiElementPointer<UDeclaration>> = emptyList())
: LocalQuickFixOnPsiElement(uDeclaration) {
override fun getFamilyName(): String = QuickFixBundle.message("fix.modifiers.family")
@@ -55,34 +55,30 @@ abstract class ImplicitSubclassProvider {
*/
abstract fun getSubclassingInfo(psiClass: PsiClass): SubclassingInfo?
/**
* Information about implicitly overridden methods.
* @property description an explanation why this method was overridden.
* @property isAbstract is overridden method abstract.
*/
class OverridingInfo @JvmOverloads constructor(@Nls(capitalization = Sentence)
val description: String,
val isAbstract: Boolean = false)
/**
* Information about implicitly created subclass.
* @property description an explanation why this class was subclassed.
* @property isAbstract is created subclass abstract.
* @property methodsInfo map of methods overridden in class and corresponding [OverridingInfo]s,
* or `null` if no method-level info is provided
*/
class SubclassingInfo @JvmOverloads constructor(@Nls(capitalization = Sentence)
val description: String,
val methodsInfo: Map<PsiMethod, OverridingInfo>? = null,
val isAbstract: Boolean = false)
companion object {
val EP_NAME = ExtensionPointName.create<ImplicitSubclassProvider>("com.intellij.codeInsight.implicitSubclassProvider")
}
}
/**
* Information about implicitly overridden methods.
* @property description an explanation why this method was overridden.
* @property isAbstract is overridden method abstract.
*/
class OverridingInfo @JvmOverloads constructor(@Nls(capitalization = Sentence)
val description: String,
val isAbstract: Boolean = false)
/**
* Information about implicitly created subclass.
* @property description an explanation why this class was subclassed.
* @property isAbstract is created subclass abstract.
*/
open class SubclassingInfo @JvmOverloads constructor(@Nls(capitalization = Sentence)
val description: String,
val isAbstract: Boolean = false) {
/**
* @param method a method of class for which the info was created.
* @return an info about reason for method overriding, or `null` if this method will not be overridden.
*/
open fun getOverridingInfo(method: PsiMethod): OverridingInfo? = null
}
@@ -825,11 +825,11 @@ inspection.reflection.invocation.argument.not.assignable=Argument is not assigna
inspection.reflection.invocation.item.not.assignable=Array item is not assignable to ''{0}''
inspection.reflection.invocation.array.not.assignable=Array {0,choice,1#item has|1<items have} incompatible {0,choice,1#type|1<types}
inspection.implicit.subclass.display.forClass=Class ''{0}'' is eligible for implicit subclassing and must not be final
inspection.implicit.subclass.display.forClass=Class ''{0}'' could be implicitly subclassed and must not be final
inspection.implicit.subclass.display.forMethod=Method ''{0}'' should be overridable
inspection.implicit.subclass.make.class.extendable=Make class ''{0}'' {1,choice,0#|1#and method {2} |1<and {1} required methods }extendable
inspection.implicit.subclass.extendable=Make ''{0}'' overridable
inspection.implicit.subclass.display.name=Final class is eligible for implicit subclassing
inspection.implicit.subclass.display.name=Final declaration can't be overridden at runtime
inspection.reflection.visibility.name=Reflective access across modules issues
@@ -16,7 +16,6 @@
package com.siyeh.ig.psiutils;
import com.intellij.codeInspection.inheritance.ImplicitSubclassProvider;
import com.intellij.codeInspection.inheritance.SubclassingInfo;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiClass;
@@ -86,7 +85,7 @@ public class InheritanceUtil {
if (!provider.isApplicableTo(aClass)) {
continue;
}
SubclassingInfo info = provider.getSubclassingInfo(aClass);
ImplicitSubclassProvider.SubclassingInfo info = provider.getSubclassingInfo(aClass);
if (info != null && !info.isAbstract()) {
return true;
}
@@ -16,10 +16,8 @@
package org.jetbrains.idea.devkit.inspections;
import com.intellij.codeInspection.inheritance.ImplicitSubclassProvider;
import com.intellij.codeInspection.inheritance.SubclassingInfo;
import com.intellij.psi.PsiClass;
import com.intellij.psi.util.InheritanceUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.devkit.DevKitBundle;
@@ -1,6 +1,6 @@
<html>
<body>
Reports if class is eligible for being subclassed at runtime by some framework (like Spring or Hibernate),
Reports if class is could be subclassed at runtime by some framework (like Spring or Hibernate),
but something in code prevents this class from being subclassed or method from being overridden.
</body>
</html>