You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

IntelliJ Scala插件获取声明依赖及依赖树的技术求助

针对IntelliJ SBT依赖分析插件的两个技术问题解决方案

问题1:获取项目所有声明依赖并支持跳转

你之前依赖SbtDependencyModifier.scala的方法覆盖场景有限,建议改用IntelliJ Scala插件提供的SbtProjectData与SbtModule相关API来覆盖多场景:

  • 遍历全项目模块:通过SbtUtil.getSbtProjects(project)获取所有SbtProject实例,再递归遍历每个项目的子模块
  • 提取全配置依赖:针对每个SbtModule,调用module.getResolvedScopedDependencies()获取包含compile、test、runtime、provided等所有配置维度的声明依赖;同时可通过module.getSbtProjectData().getLibraryDependencies()拿到原始声明的依赖坐标
  • 实现跳转逻辑:拿到依赖坐标后,通过LibraryTable.getInstance(project)匹配对应Library实例,再用library.getFiles(OrderRootType.CLASSES)获取类文件根路径,最后借助NavigationService.getInstance().navigate()实现跳转到对应类或资源;若需跳转源码,替换为OrderRootType.SOURCES定位源码文件

示例代码片段:

import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.libraries.LibraryTable
import org.jetbrains.sbt.project.data.SbtProjectData
import org.jetbrains.sbt.util.SbtUtil

def getAllDeclaredDependencies(project: Project): Seq[(String, String, String)] = {
  SbtUtil.getSbtProjects(project).flatMap { sbtProject =>
    sbtProject.getModules.flatMap { module =>
      module.getSbtProjectData().getLibraryDependencies.map { dep =>
        (dep.organization, dep.name, dep.revision)
      }
    }
  }
}

// 跳转实现示例
def navigateToDependency(project: Project, org: String, name: String, rev: String): Unit = {
  LibraryTable.getInstance(project).getLibraries.find { lib =>
    lib.getName.contains(s"$org:$name:$rev")
  }.foreach { lib =>
    lib.getFiles(com.intellij.openapi.roots.OrderRootType.CLASSES).headOption.foreach { classRoot =>
      // 可根据具体类名进一步定位到目标文件,此处省略类名匹配逻辑
      val navigationItem = // 构建对应NavigationItem实例
      com.intellij.openapi.navigation.NavigationService.getInstance().navigate(navigationItem, true)
    }
  }
}

需额外处理sbt的动态版本依赖(如通过变量声明的版本号)和子项目依赖,可通过module.getModuleDependencies()获取项目间依赖关系并递归处理。

问题2:直接获取依赖树/图

无需依赖sbt-dependency-graph插件与shell命令,可通过两种方式实现:

  1. 复用IntelliJ缓存的解析后依赖数据:
    IntelliJ Scala插件同步sbt项目时会缓存已解析依赖的层级关系,通过SbtDependencyService可直接读取。示例:
    import org.jetbrains.sbt.services.SbtDependencyService
    import org.jetbrains.sbt.util.SbtUtil
    
    def getDependencyTree(project: Project): Unit = {
      val dependencyService = SbtDependencyService.getInstance(project)
      SbtUtil.getSbtProjects(project).foreach { sbtProject =>
        sbtProject.getModules.foreach { module =>
          val resolvedDeps = dependencyService.getResolvedDependencies(module)
          // 递归遍历构建依赖树
          buildDependencyTree(resolvedDeps)
        }
      }
    }
    
    def buildDependencyTree(deps: Seq[org.jetbrains.sbt.model.SbtResolvedDependency]): Unit = {
      deps.foreach { dep =>
        println(s"${dep.module}: ${dep.revision}")
        buildDependencyTree(dep.children)
      }
    }
    
  2. 通过IntelliJ SBT Server执行内部命令:
    借助SbtRunner直接执行sbt的dependencyTree命令,插件内部临时注入sbt-dependency-graph依赖,无需用户手动配置,且复用已有SBT Server进程,启动速度更快。示例:
    import org.jetbrains.sbt.runner.SbtRunner
    import org.jetbrains.sbt.SbtUtil
    
    def fetchDependencyTreeViaSbt(project: Project): Unit = {
      val sbtRunner = SbtRunner.getInstance(project)
      val targetProject = SbtUtil.getSbtProjects(project).head
      // 临时注入插件依赖并执行命令
      val tempPluginSetting = """addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.10.0-RC1")"""
      val command = s"""set every ${tempPluginSetting}; dependencyTree"""
      sbtRunner.runCommand(targetProject, command, output => {
        // 解析命令输出构建依赖树结构
        parseDependencyTreeOutput(output)
      })
    }
    

内容的提问来源于stack exchange,提问作者梦境迷离

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 01:24:51