البرنامج المساعد استراتيجية Moxy

في بعض الأحيان تكون الأشياء البسيطة مرهقة للغاية ، خاصة عندما تحتاج إلى القيام بها باستمرار. أحد هذه الأشياء عند العمل مع إطار عمل Moxy هو إضافة استراتيجيات للوظائف. لتسريع هذه العملية ، تم كتابة مكون إضافي يوفر ، عن طريق "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, // psiElement
                StrategyIntentionType.MissingStrategy.title,  // description
                *fixes // LocalQuickFix
            )
        }
    }

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.


. - . . . .




Source: https://habr.com/ru/post/undefined/


All Articles