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

SBT多模块项目中模块与源码目录的映射方法咨询

如何实现scala/scala项目中SBT模块与源码路径的映射

问题背景

我正在尝试查找SBT构建项目中各模块对应的源码路径,以GitHub上的scala/scala项目为例,执行依赖树命令后得到一级模块列表,同时项目的src和test目录结构也已明确,但无法直接将模块与目录一一对应,需要实现模块到源码路径的映射(例如org.scala-lang:scala-reflect对应/path/src/reflect/,org.scala-lang:scalacheck对应/path/test/scalacheck/)。之前在Apache Pekko项目中使用的工件名拼接逻辑不适用于此项目,特此咨询可行方案。

现有信息

执行SBT依赖树命令得到的一级模块列表

[info] org.scala-lang:root_2.13:2.13.11-bin-SNAPSHOT [S]
[info] org.scala-lang:scala-reflect:2.13.11-bin-SNAPSHOT [S]
[info] org.scala-lang:scala-compiler:2.13.11-bin-SNAPSHOT [S]
[info] org.scala-lang:scalap:2.13.11-bin-SNAPSHOT
[info] org.scala-lang:scala-compiler-doc:2.13.11-bin-SNAPSHOT
[info] org.scala-lang:scala-compiler-interactive:2.13.11-bin-SNAPSHOT
[info] org.scala-lang:scala-tastytest:2.13.11-bin-SNAPSHOT [S]
[info] org.scala-lang:scala-testkit:2.13.11-bin-SNAPSHOT
[info] org.scala-lang:repl:2.13.11-bin-SNAPSHOT
[info] org.scala-lang:scala-dist:2.13.11-bin-SNAPSHOT [S]
[info] org.scala-lang:tasty:2.13.11-bin-SNAPSHOT
[info] org.scala-lang:scalacheck:2.13.11-bin-SNAPSHOT [S]
[info] org.scala-lang:scala-repl-frontend:2.13.11-bin-SNAPSHOT
[info] org.scala-lang:junit:2.13.11-bin-SNAPSHOT
[info] org.scala-lang:scala-partest:2.13.11-bin-SNAPSHOT [S]

项目src和test目录结构

├── src
│   ├── compiler
│   ├── intellij
│   ├── interactive
│   ├── library
│   ├── library-aux
│   ├── manual
│   ├── partest
│   ├── partest-javaagent
│   ├── reflect
│   ├── repl
│   ├── repl-frontend
│   ├── scaladoc
│   ├── scalap
│   ├── tastytest
│   └── testkit

├── test
│   ├── async
│   ├── benchmarks
│   ├── files
│   ├── instrumented
│   ├── jcstress
│   ├── junit
│   ├── macro-annot
│   ├── osgi
│   ├── scalacheck
│   ├── scaladoc
│   ├── script-tests
│   └── tasty

原有方案(不适用于scala/scala项目)

之前在Apache Pekko项目中使用的代码逻辑:

String gavid = line.substring(startIndex, line.lastIndexOf(":"));
System.out.println("GAV id: " + gavid);

String[] parts1 = gavid.split(":");
String[] parts2 = parts1[1].split("_");

int hyphenIndex = parts2[0].indexOf('-');
String directory = parts2[0].substring(hyphenIndex + 1);
new_module.setSrcCodePath(object.getSrcCodePath()  + directory + '/');

可行的映射方案

针对scala/scala项目的模块命名规则和目录结构,可采用以下逻辑实现映射:

1. 提取模块核心名称

从GAV字符串中提取工件名(即:分隔的第二部分,去掉后缀的_2.13这类Scala版本标识):

  • 对于org.scala-lang:scala-reflect:2.13.11-bin-SNAPSHOT,提取scala-reflect
  • 对于org.scala-lang:repl:2.13.11-bin-SNAPSHOT,提取repl

2. 定义名称转换规则

scala/scala项目的模块名和目录名存在固定的简化对应关系,可通过**移除前缀scala-(如果存在)**来匹配目录:

模块工件名转换后目录名
scala-reflectreflect
scala-compilercompiler
scala-tastytesttastytest
scala-testkittestkit
scala-compiler-interactiveinteractive
scala-repl-frontendrepl-frontend
scala-partestpartest
scalapscalap
replrepl
tastytasty
scalacheckscalacheck
junitjunit

3. 区分src/test目录

  • 大部分核心模块(如reflect、compiler、repl等)对应的源码在src/目录下
  • 测试相关模块(如scalacheck、junit、tasty测试部分)对应的源码在test/目录下
  • 可通过预先定义的列表判断归属:
    • 归属test/的模块:scalacheck、junit、tasty
    • 其余核心模块归属src/

4. 特殊模块单独处理

  • root_2.13:聚合根模块,无单独源码目录,可跳过或标记为特殊模块
  • scala-dist:分发聚合模块,无对应源码目录,需特殊处理
  • scala-compiler-doc:对应src/scaladoc目录,需单独映射

5. 示例代码实现(Java)

import java.util.Arrays;
import java.util.List;

public class ModulePathMapper {
    public static void main(String[] args) {
        // 示例模块行
        String line = "[info] org.scala-lang:scala-reflect:2.13.11-bin-SNAPSHOT [S]";
        mapModuleToPath(line);
    }

    public static void mapModuleToPath(String moduleLine) {
        // 提取GAV核心部分
        String gavPart = moduleLine.replace("[info] ", "").split(" ")[0];
        String[] gavParts = gavPart.split(":");
        String artifactName = gavParts[1];

        // 移除Scala版本后缀(如_2.13)
        if (artifactName.contains("_")) {
            artifactName = artifactName.split("_")[0];
        }

        // 转换为目录名
        String dirName;
        if (artifactName.startsWith("scala-")) {
            dirName = artifactName.substring(6); // 跳过"scala-"前缀(6个字符)
        } else {
            dirName = artifactName;
        }

        // 特殊模块映射
        if ("scala-compiler-doc".equals(artifactName)) {
            dirName = "scaladoc";
        }

        // 确定基础路径(src/test)
        String basePath;
        List<String> testModules = Arrays.asList("scalacheck", "junit", "tasty");
        if (testModules.contains(dirName)) {
            basePath = "/path/test/";
        } else {
            basePath = "/path/src/";
        }

        // 生成最终路径
        String finalPath = basePath + dirName + "/";
        System.out.println(gavPart + " -> " + finalPath);
    }
}

内容的提问来源于stack exchange,提问作者Sri Shylesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 13:48:13