Class RemappedSpecContext

java.lang.Object
net.fabricmc.loom.configuration.processors.speccontext.RemappedSpecContext
All Implemented Interfaces:
SpecContext

public final class RemappedSpecContext extends Object implements SpecContext
重映射形态下交给 jar processor 的 SpecContext 实现.

为什么 modDependencies 是惰性的

它是本上下文里**唯一**需要把每个 remap 配置整体 resolve() 一遍、再逐个打开 mod jar 读 fabric.mod.json 才能得出的字段(见 getDependentMods(net.fabricmc.loom.configuration.processors.speccontext.RemappedProjectView, net.fabricmc.loom.util.AsyncCache<java.util.List<net.fabricmc.loom.util.fmj.FabricModJson>>))。实测一份只声明了 一个聚合件(fabric-api)的消费方工程,该字段在配置期要 resolve 55 个 artifact、 耗时 146~3545 ms(机器负载高时更差);而 Loom 自带的三个 processor (access widener / interface injection / mod javadoc)**没有一个读它**——它们只读 localMods() 与 modDependenciesCompileRuntime()。

把它做成 Lazy 之后:没有 processor 读它就完全不解析(默认路径,收益全额落袋); 第三方 processor 读到它时结果与改造前逐位相同,只是求值点从「构建上下文时」挪到了「第一次读时」。 两者都发生在配置期,因此**不改变交给 processor 的输入集合**。

为什么不能整体推迟到执行期

processor 的 spec 由 MinecraftJarProcessorManager.create 在配置期用本上下文构建, 而 spec 的 hashCode 决定 processed jar 的产物目录名(getJarHash())与 SourceMappingsService 的 @Input 哈希。产物路径在配置期就必须确定,因此 「spec 内容 → 产物路径」这条链无法挪到执行期;能做的只有减少求值的工作量,而不是挪时机。

副作用不丢

getDependentMods(net.fabricmc.loom.configuration.processors.speccontext.RemappedProjectView, net.fabricmc.loom.util.AsyncCache<java.util.List<net.fabricmc.loom.util.fmj.FabricModJson>>) 会经 SpecContext.getDependentProjectData(net.fabricmc.loom.configuration.processors.speccontext.ProjectView) 触发依赖项目的强制求值 与跨项目数据接线。惰性化后这些副作用并未丢失:同样的读取也发生在 getCompileRuntimeProjectDependencies(net.fabricmc.loom.configuration.processors.speccontext.ProjectView),它由**非惰性**的 getCompileRuntimeMods(net.fabricmc.loom.configuration.processors.speccontext.RemappedProjectView, net.fabricmc.loom.util.AsyncCache<java.util.List<net.fabricmc.loom.util.fmj.FabricModJson>>) 无条件调用,且两者启用条件(ProjectView.disableProjectDependantMods())完全一致。