рдХрднреА-рдХрднреА рд╕рд╛рдзрд╛рд░рдг рдЪреАрдЬреЗрдВ рдмрд╣реБрдд рдердХрд╛ рджреЗрддреА рд╣реИрдВ, рдЦрд╛рд╕рдХрд░ рдЬрдм рдЙрдиреНрд╣реЗрдВ рд▓рдЧрд╛рддрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЗрди рдЪреАрдЬреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдЬрдм рдореЛрдХреНрд╕реА рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ, рддреЛ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рд░рдгрдиреАрддрд┐рдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝ рд░рд╣рд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рддреЗрдЬ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдкреНрд▓рдЧрдЗрди рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛ , рдЬреЛ "alt + enter" рджреНрд╡рд╛рд░рд╛, рд░рдгрдиреАрддрд┐ рдХрд╛ рдПрдХ рд╡рд┐рдХрд▓реНрдк рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдпрджрд┐ рдпрд╣ рдирд╣реАрдВ рд╣реИ рдпрд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рд░рдгрдиреАрддрд┐ рдХреЗ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХреЗ рд╕рд╛рде рдПрдХ рд╕рдВрд╡рд╛рдж рд╣реИред рдЬреЛ рд▓реЛрдЧ рдЬрд╛рдирдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдмрд┐рд▓реНрд▓реА рдХрд╛ рд╕реНрд╡рд╛рдЧрдд рдХрд░рддреЗ рд╣реИрдВред

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.
. - . . . .