Parfois, les choses simples sont très fatigantes, surtout lorsqu'elles doivent être effectuées en permanence. L'une de ces choses lorsque vous travaillez avec le framework Moxy consiste à ajouter des stratégies aux fonctions. Pour accélérer ce processus, un plugin a été écrit qui, par "alt + enter", permet de choisir une stratégie si elle n'est pas là ou un dialogue avec un remplacement pour une autre stratégie. Ceux qui veulent savoir comment cela fonctionne, bienvenue chez cat.

Moxy, . , .
, adev_one , .
Inspection
, . code inspections. PSI (Program Structure Interface), , , alt+enter .
code inspections.
PSI — , , .. , , parent child. , , Psi viewer plugin.
.
, KtNamedFunction.
Inpection.
. plugins.xml
<depends>org.jetbrains.kotlin</depends>
<depends>com.intellij.modules.lang</depends>
build.gradle
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "org.jetbrains.kotlin:kotlin-reflect"
implementation "com.github.moxy-community:moxy:1.0.13"
}
intellij {
...
plugins = ["Kotlin"]
...
}
inpection.
AbstractKotlinInspection
class MvpViewStrategyInspection : AbstractKotlinInspection() {}
:
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor
Visitor, .
Visitor , kotlin - Visitor. KtNamedFunction :
org.jetbrains.kotlin.psi VisitorWrappersKt.class
public fun namedFunctionVisitor(block: (KtNamedFunction) → Unit): KtVisitorVoid
PSI: , MvpView. , ProblemsHolder.
:
private val fixes = MoxyStrategy.values().map { AddStrategyFix(it) }.toTypedArray()
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return namedFunctionVisitor { ktNamedFunction ->
if (!ktNamedFunction.isClassInheritMvpView() ||
ktNamedFunction.isHasMoxyAnnotation()
) return@namedFunctionVisitor
holder.registerProblem(
ktNamedFunction,
StrategyIntentionType.MissingStrategy.title,
*fixes
)
}
}
AddStrategyFix? , LocalQuickFix. , :
class AddStrategyFix(
private val strategy: MoxyStrategy
) : LocalQuickFix {
override fun getFamilyName(): String = "add ${strategy.className}"
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val ktFunction = (descriptor.psiElement as KtNamedFunction)
val editor = ktFunction.getProjectEditor()
ktFunction.addStrategyAnnotation(strategy, project, editor)
}
}
getFamilyName
— , .
applyFix
. .
Inspection plguin.xml, ( Activity Manifest)
<extensions defaultExtensionNs="com.intellij">
<localInspection language="kotlin"
displayName="missing strategy for function"
groupPath="Moxy"
groupBundle="messages.InspectionsBundle"
groupKey="group.names.probable.bugs"
enabledByDefault="true"
level="ERROR"
implementationClass="com.maksimnovikov.inspection.MvpViewStrategyInspection"/>
</extensions>
:

StateStrategyType
.
AddToEndSingleTagStrategy
tag
.

Intention
, . .
Intention.
Inspection, . intention. .
Intention.
PsiElementBaseIntentionAction
:
class MvpViewStrategyIntention : PsiElementBaseIntentionAction(){
override fun getText(): String
override fun getFamilyName(): String
override fun isAvailable(project: Project, editor: Editor?, element: PsiElement): Boolean
override fun invoke(project: Project, editor: Editor?, element: PsiElement)
}
getText —
getFamilyName — intention
isAvailable — , intention .
invoke — , intention
isAvailable invoke:
isAvailable
, intention . .
child , . .
override fun isAvailable(project: Project, editor: Editor?, element: PsiElement): Boolean {
if ((element.containingFile ?: return false) !is KtFile) return false
if (!element.isClassInheritMvpView()) return false
val ktFunction = element.getParentOfType<KtNamedFunction>() ?: return false
return ktFunction.isHasMoxyAnnotation()
}
invoke
Intention , .
IDE swing. , , . — JBPopupFactory
fun <T> Editor.showSelectPopup(
items: List<T>,
onSelected: (T) -> Unit
) {
JBPopupFactory.getInstance()
.createPopupChooserBuilder(items)
.setRequestFocus(true)
.setCancelOnClickOutside(true)
.setItemChosenCallback { onSelected(it) }
.createPopup()
.showInBestPositionFor(this)
}
, , . WriteCommandAction.runWriteCommandAction(project) {}
override fun invoke(project: Project, editor: Editor, element: PsiElement) {
editor.showSelectPopup(MoxyStrategy.values().toList()) { selectedStrategy ->
WriteCommandAction.runWriteCommandAction(project) {
val ktFunction = element.getParentOfType<KtNamedFunction>() ?: return@runWriteCommandAction
ktFunction.replaceAnnotation(selectedStrategy, project, editor)
}
}
}
intention plugin.xml
<extensions defaultExtensionNs="com.intellij">
<intentionAction>
<className>com.maksimnovikov.intention.MvpViewStrategyIntention</className>
<category>Moxy intentions</category>
</intentionAction>
</extensions>
:


. . , , . Moxy.
. - . . . .