前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为 TheRouter 开发一个 IDEA 插件

为 TheRouter 开发一个 IDEA 插件

作者头像
用户1907613
发布2023-10-19 16:11:22
3030
发布2023-10-19 16:11:22
举报
文章被收录于专栏:Android群英传

为 TheRouter 开发一个 IDEA 插件

❝本插件代码已全部开源,走过路过请给个star: https://github.com/kymjs/TheRouterIdeaPlugin ❞

这篇文章是假定你已经有了 idea 插件开发的入门知识,来教你如何实现一个实际项目的功能。如果你还不知道如何开发一个插件,建议先从这个链接查看官网相关文档 https://plugins.jetbrains.com/docs/intellij/welcome.html。

背景介绍

TheRouter 是一个移动端动态路由框架,同时支持 Android、iOS,具有高度双端一致性,可以把原本类依赖解耦为字符串依赖。 做过 Android 开发的应该都知道,页面跳转强行跟Activity.class绑定的,所以大部分路由框架都会把class替换成一个字符串,用字符串来解耦,但是这样一来就又变成了字符串满天飞的情况。 所以我做了这个用于自动跳转的高效辅助插件,可以直接从路由的声明处查看到哪些地方跳转到本路由,再也不用怕路由字符串满天飞了。

需要哪些功能

页面跳转

先想想需要哪些功能,首先页面跳转肯定是要有个导航的。类似这张图,在路由声明的地方,只需要点一下侧面的导航箭头,就能跳转到所有使用了这个路由页面的地方,并且还能标记出有哪些类用到了他。

http://therouter.cn/assets/img/image/ideaplugin1.png

版本号更新

对于开源项目,最麻烦的就是什么时候有新版本,新版本修复了什么问题。类似这张图,如果能有一个提醒,每次有新版本就告诉我,新版本有什么功能,修复了什么问题,跟我当前使用的版本有哪些变化,直接升级需不需要改代码,那就方便很多了。

http://therouter.cn/assets/img/image/ideaplugin1.png

一键迁移工具

TheRouter 官网本身提供了一个图形化界面的迁移工具,可以直接从其他路由迁移到TheRouter。但是使用的时候还得要额外下载一个APP,既然代码都是开源的,如果这个功能直接放在开发工具里面,那就方便多了。

https://therouter.cn/assets/img/image/TheRouterTransfer.png

导航跳转是如何实现的

在 idea 插件的开发中,有个很重要的类就是 LineMarkerProvider ,他是 Jetbrains 提供的 SDK 中的类。他是代码中每一行的标记提供者,也就对应了上面图中代码侧面的标记,是如何创建的。 比如在给 TheRouter 设计的这个插件里,就用这样的代码创建了一个侧边栏行标记:

代码语言:javascript
复制
if (allMarkerStatus[key] != STATUS_SHOWN) {
    allMarkerStatus[key] = STATUS_SHOWN
    val builder = NavigationGutterIconBuilder.create(getIcon(targetContent.type))
    builder.setAlignment(GutterIconRenderer.Alignment.CENTER)
    builder.setTargets(all)
    if (targetContent.type == TYPE_ANNOTATION || targetContent.type == TYPE_ACTION) {
        builder.setTooltipTitle("TheRouter:跳转到使用处")
    } else {
        builder.setTooltipTitle("TheRouter:跳转到声明处")
    }
    result.add(builder.createLineMarkerInfo(psiElement))
}

其中的 NavigationGutterIconBuilder.create()就是创建一个侧边栏行标记,入参是一个图片资源,这里我根据要展示的类型返回了不同的资源图片。

代码语言:javascript
复制
fun getIcon(type: Int): Icon {
    return when (type) {
        TYPE_ANNOTATION -> IconLoader.getIcon("/icon/icon_from.png")
        TYPE_NAVIGATION -> IconLoader.getIcon("/icon/icon_to.png")
        TYPE_ACTION -> IconLoader.getIcon("/icon/icon_from.png")
        else -> IconLoader.getIcon("/icon/icon_warn.png")
    }
}
找到要跳转的psi

解决了显示的标记,剩下的就是找到点击标记后要跳到哪里了。 在 idea 插件的 SDK 中,还有个很重要的类就是 PsiElement,PSI (Program Structure Interface),指程序结构接口,主要负责解析文件、创建语法、语义代码。一个 PsiElement 就表示了一个我们要处理的代码语句。 在上面代码的builder里面有一个重要的方法是builder.setTargets(),就表示点击这个图标后要跳到哪里,上面的代码中传入的all 是一个PsiElement集合,如果只有一个PsiElement,点击以后就会直接跳转,如果集合有多个元素,则会先展示一个选择框,由插件的使用方自行选择跳到哪个目标PsiElement。 而这个all集合的获取,也是来自另一个SDK中的方法PsiManager.getInstance(project).findFile(virtualFile),他可以将整个项目中的所有代码以 psi 的方式返回给你,这样你就可以根据实际需要,过滤找到跳转的目标位置了。具体使用可以看下面这段节选代码:

代码语言:javascript
复制
private fun findAllTargetPsi(
    project: Project,
    filePath: String?,
    target: TargetContent
): Collection<TargetPsiElement> {
    val allTargetPsi = HashSet<TargetPsiElement>()
    val scopes = GlobalSearchScope.projectScope(project)
    val allCodeFiles = FilenameIndex.getAllFilesByExt(project, "kt", scopes)
    allCodeFiles.addAll(javaFiles)
    for (virtualFile in allCodeFiles) {
        val psiFile: PsiFile? = PsiManager.getInstance(project).findFile(virtualFile)
        psiFile ?: return HashSet()

        val properties = PsiTreeUtil.findChildrenOfType(psiFile, PsiElement::class.java)
        properties.forEach { psiElement ->
   allTargetPsi.add(TargetPsiElement(psiElement, psiFile.name))
        }
    }
    return allTargetPsi
}

迁移工具是如何实现的

有个最简单的原因,TheRouter在设计阶段就参考了大量其他路由的设计,根据官网的描述:

❝之所以叫TheRouter 因为 The 代表了一种唯一性,我们在设计的时候就参考了全部现有的开源方案,吸取了大量优秀实现,同时补齐了各个方案的缺点。 ❞

所以本身在 API 层面,TheRouter 跟其他的路由就没有什么区别,因此迁移工具的核心就是「字符串替换」,这里替换的内容没什么好讲的,重点讲讲如何在插件里面展示一个UI弹窗。

首先第一步是创建一个AnAction类,他也是 Jetbrains 提供的 SDK 中的类。用于在菜单栏中展示一个菜单项,就像这样:

同样SDK也已经提供好了弹窗的API,跟开发 Android 一样,直接调用MessageDialogBuilder就可以创建了。

代码语言:javascript
复制
class TransferAction : AnAction() {
    private val routerNameList = HashMap<String, ITransfer>()
    override fun actionPerformed(event: AnActionEvent) {
        val project = event.project ?: return
        val version = getVersion()
        val file = File(desktop, fileName)
        if (MessageDialogBuilder
                .okCancel(
                    "TheRouter 一键迁移工具",
                    "当前项目为:$projectPath\n\n即将迁移至 TheRouter $latestVersion。迁移完成后,会在桌面生成改动日志。请注意查看:\n\n${file.absolutePath}。"
                )
                .noText("取消")
                .yesText("开始迁移")
                .icon(Messages.getInformationIcon())
                .ask(project)
        ) {
            routerNameList["ARouter"]?.transfer(projectPath, latestVersion, file)
        }
    }
}

插件开源

本项目已基于 Apache License 2.0 协议开源,并上架插件市场,欢迎 star 与下载

GitHub:https://github.com/kymjs/TheRouterIdeaPlugin

插件下载: https://plugins.jetbrains.com/plugin/20047-therouter

插件下载

  1. 打开 Android Studio -> Preferences -> Plugins -> Marketplace
  2. 搜索 TheRouter
  3. 点击下载
  4. 重启 Android Studio

https://therouter.cn/assets/img/image/TheRouterIdeaPlugin.jpg

向大家推荐下我的网站 https://www.yuque.com/xuyisheng 点击原文一键直达

专注 Android-Kotlin-Flutter 欢迎大家访问

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-10-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 群英传 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景介绍
  • 需要哪些功能
    • 页面跳转
      • 版本号更新
        • 一键迁移工具
        • 导航跳转是如何实现的
          • 找到要跳转的psi
          • 迁移工具是如何实现的
          • 插件开源
          • 插件下载
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档