@cdxgen/cdxgen 13.3.0 → 13.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/README.md +9 -6
  2. package/bin/cdxgen.js +90 -26
  3. package/bin/evinse.js +18 -1
  4. package/bin/repl.js +86 -0
  5. package/bin/sign.js +45 -15
  6. package/bin/tracebom.js +5 -1
  7. package/bin/validate.js +84 -18
  8. package/bin/verify.js +155 -86
  9. package/data/helpers/init.gradle +46 -21
  10. package/data/remediations.json +61 -0
  11. package/data/rules/dependency-sources.yaml +67 -0
  12. package/data/rules/scala-evidence.yaml +115 -0
  13. package/lib/audit/index.js +38 -6
  14. package/lib/cli/index.js +113 -54
  15. package/lib/cli/jsBom.js +50 -29
  16. package/lib/cli/jvmBom.js +665 -138
  17. package/lib/cli/managedBom.js +320 -200
  18. package/lib/cli/nativeBom.js +139 -30
  19. package/lib/core/activity.js +12 -0
  20. package/lib/core/env.js +17 -9
  21. package/lib/core/fs.js +3 -2
  22. package/lib/core/httpClient.js +159 -24
  23. package/lib/core/pluginRun.js +184 -0
  24. package/lib/core/processTree.js +100 -0
  25. package/lib/core/runState.js +39 -0
  26. package/lib/core/toml.js +72 -0
  27. package/lib/ecosystems/asarutils.js +4 -2
  28. package/lib/ecosystems/bunutils.js +5 -7
  29. package/lib/ecosystems/cargoCache.js +231 -8
  30. package/lib/ecosystems/cmakeResolver.js +10 -21
  31. package/lib/ecosystems/cppBuildContext.js +631 -0
  32. package/lib/ecosystems/cppEvidence.js +337 -22
  33. package/lib/ecosystems/cppIncludeResolver.js +294 -0
  34. package/lib/ecosystems/denoutils.js +93 -66
  35. package/lib/ecosystems/ecosystems.js +1967 -788
  36. package/lib/ecosystems/golem.js +28 -12
  37. package/lib/ecosystems/gradleutils.js +314 -30
  38. package/lib/ecosystems/jsEvidence.js +85 -24
  39. package/lib/ecosystems/kosi.js +21 -4
  40. package/lib/ecosystems/npmutils.js +64 -0
  41. package/lib/ecosystems/parsers-dotnet.js +567 -151
  42. package/lib/ecosystems/parsers-elm.js +46 -28
  43. package/lib/ecosystems/parsers-gleam.js +3 -4
  44. package/lib/ecosystems/parsers-go.js +324 -61
  45. package/lib/ecosystems/parsers-js.js +92 -26
  46. package/lib/ecosystems/parsers-julia.js +2 -3
  47. package/lib/ecosystems/parsers-jvm.js +204 -12
  48. package/lib/ecosystems/parsers-misc.js +182 -55
  49. package/lib/ecosystems/parsers-python.js +141 -10
  50. package/lib/ecosystems/parsers-rust.js +4 -4
  51. package/lib/ecosystems/parsers-terraform.js +1573 -19
  52. package/lib/ecosystems/pythonutils.js +102 -6
  53. package/lib/ecosystems/remote/huggingface.js +3 -0
  54. package/lib/ecosystems/rubyutils.js +67 -17
  55. package/lib/ecosystems/rusi.js +22 -9
  56. package/lib/ecosystems/sbtutils.js +243 -187
  57. package/lib/ecosystems/scalacliutils.js +342 -0
  58. package/lib/ecosystems/scalasem.js +2618 -0
  59. package/lib/ecosystems/terraformRegistry.js +288 -0
  60. package/lib/ecosystems/utils.js +2 -0
  61. package/lib/ecosystems/vendoredCode.js +156 -0
  62. package/lib/evinser/evinser.js +578 -69
  63. package/lib/helpers/agenticToolutils.js +2 -2
  64. package/lib/helpers/bomSigner.js +576 -128
  65. package/lib/inventory/aiCollector.js +4 -1
  66. package/lib/inventory/analyzer.js +110 -127
  67. package/lib/inventory/atomUtils.js +171 -48
  68. package/lib/inventory/auditCategories.js +7 -0
  69. package/lib/inventory/buildToolRateLimit.js +144 -0
  70. package/lib/inventory/cacheCommands.js +2 -1
  71. package/lib/inventory/cmakeBuildDirs.js +254 -0
  72. package/lib/inventory/deps.js +501 -124
  73. package/lib/inventory/dosai.js +248 -44
  74. package/lib/inventory/dosaiParsers.js +310 -15
  75. package/lib/inventory/dynamic.js +52 -6
  76. package/lib/inventory/evidenceUtils.js +154 -109
  77. package/lib/inventory/fetchBatch.js +574 -38
  78. package/lib/inventory/fetchDiskCache.js +597 -0
  79. package/lib/inventory/forgeEnricher.js +14 -5
  80. package/lib/inventory/jvmLocalRepos.js +917 -0
  81. package/lib/inventory/mcpConfigParser.js +2 -3
  82. package/lib/inventory/parentSelection.js +146 -0
  83. package/lib/inventory/rustFormulationParser.js +3 -4
  84. package/lib/inventory/scalaCoords.js +153 -0
  85. package/lib/inventory/source.js +8 -8
  86. package/lib/inventory/spdx.js +101 -0
  87. package/lib/inventory/traceRunner.js +88 -7
  88. package/lib/inventory/tracedCrypto.js +294 -0
  89. package/lib/managers/docker.js +33 -32
  90. package/lib/managers/oci.js +24 -2
  91. package/lib/parsers/cmakeCache.js +69 -0
  92. package/lib/parsers/cmakeLists.js +16 -2
  93. package/lib/parsers/cmakePresets.js +400 -0
  94. package/lib/parsers/compileCommands.js +557 -0
  95. package/lib/parsers/strictJson.js +322 -0
  96. package/lib/parsers/terraformConfig.js +1073 -0
  97. package/lib/parsers/terraformSource.js +652 -0
  98. package/lib/server/server.js +23 -0
  99. package/lib/stages/postgen/introspection/markers.js +1 -1
  100. package/lib/stages/postgen/postgen.js +15 -1
  101. package/lib/stages/postgen/specVersionCompat.js +32 -0
  102. package/lib/validator/index.js +25 -10
  103. package/lib/validator/reporters/json.js +1 -0
  104. package/package.json +21 -21
  105. package/types/lib/audit/index.d.ts.map +1 -1
  106. package/types/lib/cli/index.d.ts.map +1 -1
  107. package/types/lib/cli/jsBom.d.ts.map +1 -1
  108. package/types/lib/cli/jvmBom.d.ts +24 -1
  109. package/types/lib/cli/jvmBom.d.ts.map +1 -1
  110. package/types/lib/cli/managedBom.d.ts +7 -4
  111. package/types/lib/cli/managedBom.d.ts.map +1 -1
  112. package/types/lib/cli/nativeBom.d.ts +3 -1
  113. package/types/lib/cli/nativeBom.d.ts.map +1 -1
  114. package/types/lib/core/activity.d.ts.map +1 -1
  115. package/types/lib/core/env.d.ts +9 -0
  116. package/types/lib/core/env.d.ts.map +1 -1
  117. package/types/lib/core/fs.d.ts.map +1 -1
  118. package/types/lib/core/httpClient.d.ts +13 -8
  119. package/types/lib/core/httpClient.d.ts.map +1 -1
  120. package/types/lib/core/pluginRun.d.ts +97 -0
  121. package/types/lib/core/pluginRun.d.ts.map +1 -0
  122. package/types/lib/core/processTree.d.ts +36 -0
  123. package/types/lib/core/processTree.d.ts.map +1 -0
  124. package/types/lib/core/runState.d.ts +29 -0
  125. package/types/lib/core/runState.d.ts.map +1 -0
  126. package/types/lib/core/toml.d.ts +20 -0
  127. package/types/lib/core/toml.d.ts.map +1 -0
  128. package/types/lib/ecosystems/asarutils.d.ts.map +1 -1
  129. package/types/lib/ecosystems/bunutils.d.ts.map +1 -1
  130. package/types/lib/ecosystems/cargoCache.d.ts +12 -0
  131. package/types/lib/ecosystems/cargoCache.d.ts.map +1 -1
  132. package/types/lib/ecosystems/cmakeResolver.d.ts +5 -3
  133. package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -1
  134. package/types/lib/ecosystems/cppBuildContext.d.ts +55 -0
  135. package/types/lib/ecosystems/cppBuildContext.d.ts.map +1 -0
  136. package/types/lib/ecosystems/cppEvidence.d.ts +18 -2
  137. package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
  138. package/types/lib/ecosystems/cppIncludeResolver.d.ts +92 -0
  139. package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -0
  140. package/types/lib/ecosystems/denoutils.d.ts +9 -3
  141. package/types/lib/ecosystems/denoutils.d.ts.map +1 -1
  142. package/types/lib/ecosystems/ecosystems.d.ts +62 -13
  143. package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
  144. package/types/lib/ecosystems/golem.d.ts.map +1 -1
  145. package/types/lib/ecosystems/gradleutils.d.ts +50 -0
  146. package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
  147. package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
  148. package/types/lib/ecosystems/kosi.d.ts.map +1 -1
  149. package/types/lib/ecosystems/npmutils.d.ts +15 -0
  150. package/types/lib/ecosystems/npmutils.d.ts.map +1 -1
  151. package/types/lib/ecosystems/parsers-dotnet.d.ts +118 -4
  152. package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
  153. package/types/lib/ecosystems/parsers-elm.d.ts.map +1 -1
  154. package/types/lib/ecosystems/parsers-gleam.d.ts.map +1 -1
  155. package/types/lib/ecosystems/parsers-go.d.ts +44 -2
  156. package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
  157. package/types/lib/ecosystems/parsers-js.d.ts +6 -1
  158. package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
  159. package/types/lib/ecosystems/parsers-julia.d.ts.map +1 -1
  160. package/types/lib/ecosystems/parsers-jvm.d.ts +46 -1
  161. package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
  162. package/types/lib/ecosystems/parsers-misc.d.ts +3 -1
  163. package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
  164. package/types/lib/ecosystems/parsers-python.d.ts +53 -3
  165. package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
  166. package/types/lib/ecosystems/parsers-terraform.d.ts +38 -21
  167. package/types/lib/ecosystems/parsers-terraform.d.ts.map +1 -1
  168. package/types/lib/ecosystems/pythonutils.d.ts +27 -2
  169. package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
  170. package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
  171. package/types/lib/ecosystems/rubyutils.d.ts +21 -1
  172. package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
  173. package/types/lib/ecosystems/rusi.d.ts.map +1 -1
  174. package/types/lib/ecosystems/sbtutils.d.ts +88 -2
  175. package/types/lib/ecosystems/sbtutils.d.ts.map +1 -1
  176. package/types/lib/ecosystems/scalacliutils.d.ts +56 -0
  177. package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -0
  178. package/types/lib/ecosystems/scalasem.d.ts +311 -0
  179. package/types/lib/ecosystems/scalasem.d.ts.map +1 -0
  180. package/types/lib/ecosystems/terraformRegistry.d.ts +9 -0
  181. package/types/lib/ecosystems/terraformRegistry.d.ts.map +1 -0
  182. package/types/lib/ecosystems/utils.d.ts +2 -2
  183. package/types/lib/ecosystems/utils.d.ts.map +1 -1
  184. package/types/lib/ecosystems/vendoredCode.d.ts +32 -0
  185. package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -0
  186. package/types/lib/evinser/evinser.d.ts +75 -8
  187. package/types/lib/evinser/evinser.d.ts.map +1 -1
  188. package/types/lib/helpers/bomSigner.d.ts +80 -4
  189. package/types/lib/helpers/bomSigner.d.ts.map +1 -1
  190. package/types/lib/inventory/aiCollector.d.ts.map +1 -1
  191. package/types/lib/inventory/analyzer.d.ts.map +1 -1
  192. package/types/lib/inventory/atomUtils.d.ts +82 -10
  193. package/types/lib/inventory/atomUtils.d.ts.map +1 -1
  194. package/types/lib/inventory/auditCategories.d.ts +3 -0
  195. package/types/lib/inventory/auditCategories.d.ts.map +1 -1
  196. package/types/lib/inventory/buildToolRateLimit.d.ts +38 -0
  197. package/types/lib/inventory/buildToolRateLimit.d.ts.map +1 -0
  198. package/types/lib/inventory/cacheCommands.d.ts +2 -1
  199. package/types/lib/inventory/cacheCommands.d.ts.map +1 -1
  200. package/types/lib/inventory/cmakeBuildDirs.d.ts +58 -0
  201. package/types/lib/inventory/cmakeBuildDirs.d.ts.map +1 -0
  202. package/types/lib/inventory/deps.d.ts +59 -1
  203. package/types/lib/inventory/deps.d.ts.map +1 -1
  204. package/types/lib/inventory/dosai.d.ts +57 -8
  205. package/types/lib/inventory/dosai.d.ts.map +1 -1
  206. package/types/lib/inventory/dosaiParsers.d.ts +53 -7
  207. package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
  208. package/types/lib/inventory/dynamic.d.ts +10 -0
  209. package/types/lib/inventory/dynamic.d.ts.map +1 -1
  210. package/types/lib/inventory/evidenceUtils.d.ts +19 -4
  211. package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
  212. package/types/lib/inventory/fetchBatch.d.ts +83 -14
  213. package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
  214. package/types/lib/inventory/fetchDiskCache.d.ts +169 -0
  215. package/types/lib/inventory/fetchDiskCache.d.ts.map +1 -0
  216. package/types/lib/inventory/forgeEnricher.d.ts.map +1 -1
  217. package/types/lib/inventory/jvmLocalRepos.d.ts +178 -0
  218. package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -0
  219. package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
  220. package/types/lib/inventory/parentSelection.d.ts +34 -0
  221. package/types/lib/inventory/parentSelection.d.ts.map +1 -0
  222. package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
  223. package/types/lib/inventory/scalaCoords.d.ts +80 -0
  224. package/types/lib/inventory/scalaCoords.d.ts.map +1 -0
  225. package/types/lib/inventory/source.d.ts.map +1 -1
  226. package/types/lib/inventory/spdx.d.ts +9 -0
  227. package/types/lib/inventory/spdx.d.ts.map +1 -1
  228. package/types/lib/inventory/traceRunner.d.ts +12 -0
  229. package/types/lib/inventory/traceRunner.d.ts.map +1 -1
  230. package/types/lib/inventory/tracedCrypto.d.ts +42 -0
  231. package/types/lib/inventory/tracedCrypto.d.ts.map +1 -0
  232. package/types/lib/managers/docker.d.ts.map +1 -1
  233. package/types/lib/managers/oci.d.ts +3 -1
  234. package/types/lib/managers/oci.d.ts.map +1 -1
  235. package/types/lib/parsers/cmakeCache.d.ts +16 -0
  236. package/types/lib/parsers/cmakeCache.d.ts.map +1 -1
  237. package/types/lib/parsers/cmakeLists.d.ts +2 -1
  238. package/types/lib/parsers/cmakeLists.d.ts.map +1 -1
  239. package/types/lib/parsers/cmakePresets.d.ts +78 -0
  240. package/types/lib/parsers/cmakePresets.d.ts.map +1 -0
  241. package/types/lib/parsers/compileCommands.d.ts +115 -0
  242. package/types/lib/parsers/compileCommands.d.ts.map +1 -0
  243. package/types/lib/parsers/strictJson.d.ts +46 -0
  244. package/types/lib/parsers/strictJson.d.ts.map +1 -0
  245. package/types/lib/parsers/terraformConfig.d.ts +70 -0
  246. package/types/lib/parsers/terraformConfig.d.ts.map +1 -0
  247. package/types/lib/parsers/terraformSource.d.ts +66 -0
  248. package/types/lib/parsers/terraformSource.d.ts.map +1 -0
  249. package/types/lib/server/server.d.ts.map +1 -1
  250. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  251. package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
  252. package/types/lib/validator/index.d.ts +8 -0
  253. package/types/lib/validator/index.d.ts.map +1 -1
  254. package/types/lib/validator/reporters/json.d.ts.map +1 -1
  255. package/lib/third-party/arborist/snapshots/calc-dep-flags.test.cjs +0 -462
@@ -0,0 +1,400 @@
1
+ /**
2
+ * Pure reader for CMake presets (`CMakePresets.json` and
3
+ * `CMakeUserPresets.json`, schema versions 1 to 10).
4
+ *
5
+ * A configure preset names how a project is configured: the generator, the
6
+ * build directory, the toolchain file and the cache variables (build type,
7
+ * compilers). Presets inherit from one another, may be hidden (templates
8
+ * that only exist to be inherited), may be enabled only under a condition,
9
+ * and spell paths with macros such as `${sourceDir}` and `$env{NAME}`.
10
+ *
11
+ * This module is layer 1: text and a context object in, data out. Reading the
12
+ * files (and their `include` lists) is done by the caller, which also supplies
13
+ * the process environment through `context.penv`.
14
+ */
15
+
16
+ import { isAbsolute, join, normalize } from "node:path";
17
+
18
+ /** Fields a preset does not inherit (CMake's rule). */
19
+ const NOT_INHERITED = new Set([
20
+ "name",
21
+ "hidden",
22
+ "inherits",
23
+ "description",
24
+ "displayName",
25
+ ]);
26
+
27
+ /** Fields merged key by key across the inheritance chain. */
28
+ const MAP_FIELDS = new Set(["cacheVariables", "environment"]);
29
+
30
+ /** An inheritance chain deeper than this is treated as malformed. */
31
+ const MAX_INHERITANCE_DEPTH = 32;
32
+
33
+ /**
34
+ * Parse the text of a presets file.
35
+ *
36
+ * @param {string} text File contents
37
+ * @returns {{version: number|undefined, include: string[], configurePresets: Object[]}|null}
38
+ * `null` when the text is not a presets document
39
+ */
40
+ export function parseCmakePresets(text) {
41
+ if (typeof text !== "string" || !text.trim()) {
42
+ return null;
43
+ }
44
+ let data;
45
+ try {
46
+ data = JSON.parse(text);
47
+ } catch (_err) {
48
+ return null;
49
+ }
50
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
51
+ return null;
52
+ }
53
+ const configurePresets = Array.isArray(data.configurePresets)
54
+ ? data.configurePresets.filter(
55
+ (p) =>
56
+ p &&
57
+ typeof p === "object" &&
58
+ !Array.isArray(p) &&
59
+ typeof p.name === "string" &&
60
+ p.name.length,
61
+ )
62
+ : [];
63
+ return {
64
+ version: Number.isInteger(data.version) ? data.version : undefined,
65
+ include: Array.isArray(data.include)
66
+ ? data.include.filter((f) => typeof f === "string" && f.length)
67
+ : [],
68
+ configurePresets,
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Expand the macros CMake allows in preset strings.
74
+ *
75
+ * Supported: `${sourceDir}`, `${sourceParentDir}`, `${sourceDirName}`,
76
+ * `${presetName}`, `${generator}`, `${hostSystemName}`, `${fileDir}`,
77
+ * `${dollar}`, `${pathListSep}`, `$env{NAME}` (the preset's own environment,
78
+ * then the process environment) and `$penv{NAME}` (the process environment).
79
+ * `$vendor{...}` and unknown macros are left as written.
80
+ *
81
+ * @param {string} value String to expand
82
+ * @param {Object} context Macro values; `env` (preset environment, a plain
83
+ * object) and `penv` (a function reading the process environment) are
84
+ * optional
85
+ * @returns {string} Expanded string
86
+ */
87
+ export function expandPresetMacros(value, context = {}) {
88
+ if (typeof value !== "string" || !value.includes("$")) {
89
+ return value;
90
+ }
91
+ let out = "";
92
+ let i = 0;
93
+ while (i < value.length) {
94
+ const dollar = value.indexOf("$", i);
95
+ if (dollar < 0) {
96
+ out += value.slice(i);
97
+ break;
98
+ }
99
+ out += value.slice(i, dollar);
100
+ const open = value.indexOf("{", dollar);
101
+ const close = open < 0 ? -1 : value.indexOf("}", open);
102
+ const namespace = open < 0 ? "" : value.slice(dollar + 1, open);
103
+ if (
104
+ open < 0 ||
105
+ close < 0 ||
106
+ !["", "env", "penv", "vendor"].includes(namespace)
107
+ ) {
108
+ out += "$";
109
+ i = dollar + 1;
110
+ continue;
111
+ }
112
+ const name = value.slice(open + 1, close);
113
+ const replacement = macroValue(namespace, name, context);
114
+ out +=
115
+ replacement === undefined ? value.slice(dollar, close + 1) : replacement;
116
+ i = close + 1;
117
+ }
118
+ return out;
119
+ }
120
+
121
+ function macroValue(namespace, name, context) {
122
+ if (namespace === "penv") {
123
+ return context.penv ? (context.penv(name) ?? "") : "";
124
+ }
125
+ if (namespace === "env") {
126
+ if (context.env && Object.hasOwn(context.env, name)) {
127
+ return context.env[name] ?? "";
128
+ }
129
+ return context.penv ? (context.penv(name) ?? "") : "";
130
+ }
131
+ if (namespace === "vendor") {
132
+ return undefined;
133
+ }
134
+ switch (name) {
135
+ case "sourceDir":
136
+ case "sourceParentDir":
137
+ case "sourceDirName":
138
+ case "presetName":
139
+ case "generator":
140
+ case "hostSystemName":
141
+ case "fileDir":
142
+ case "pathListSep":
143
+ return context[name] ?? "";
144
+ case "dollar":
145
+ return "$";
146
+ default:
147
+ return undefined;
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Evaluate a preset condition (schema version 3 and later).
153
+ *
154
+ * @param {*} condition Condition object (or boolean, or null)
155
+ * @param {function(string): string} expand Macro expander for the preset
156
+ * @returns {boolean|undefined} `undefined` when the condition cannot be
157
+ * decided here: `matches`/`notMatches` take a regular expression from the
158
+ * repository, which is not run
159
+ */
160
+ export function evaluatePresetCondition(condition, expand) {
161
+ if (condition === null || condition === undefined) {
162
+ return true;
163
+ }
164
+ if (typeof condition === "boolean") {
165
+ return condition;
166
+ }
167
+ if (typeof condition !== "object" || Array.isArray(condition)) {
168
+ return undefined;
169
+ }
170
+ const str = (v) => (typeof v === "string" ? expand(v) : undefined);
171
+ switch (condition.type) {
172
+ case "const":
173
+ return typeof condition.value === "boolean" ? condition.value : undefined;
174
+ case "equals":
175
+ case "notEquals": {
176
+ const lhs = str(condition.lhs);
177
+ const rhs = str(condition.rhs);
178
+ if (lhs === undefined || rhs === undefined) {
179
+ return undefined;
180
+ }
181
+ return (lhs === rhs) === (condition.type === "equals");
182
+ }
183
+ case "inList":
184
+ case "notInList": {
185
+ const needle = str(condition.string);
186
+ if (needle === undefined || !Array.isArray(condition.list)) {
187
+ return undefined;
188
+ }
189
+ const found = condition.list.some((v) => str(v) === needle);
190
+ return found === (condition.type === "inList");
191
+ }
192
+ case "anyOf":
193
+ case "allOf": {
194
+ if (!Array.isArray(condition.conditions)) {
195
+ return undefined;
196
+ }
197
+ const results = condition.conditions.map((c) =>
198
+ evaluatePresetCondition(c, expand),
199
+ );
200
+ if (condition.type === "anyOf") {
201
+ if (results.includes(true)) {
202
+ return true;
203
+ }
204
+ return results.includes(undefined) ? undefined : false;
205
+ }
206
+ if (results.includes(false)) {
207
+ return false;
208
+ }
209
+ return results.includes(undefined) ? undefined : true;
210
+ }
211
+ case "not": {
212
+ const inner = evaluatePresetCondition(condition.condition, expand);
213
+ return inner === undefined ? undefined : !inner;
214
+ }
215
+ default:
216
+ return undefined;
217
+ }
218
+ }
219
+
220
+ /** A cache variable's value as CMake sets it, or `null` for an unset one. */
221
+ function cacheValue(entry) {
222
+ if (entry === null) {
223
+ return null;
224
+ }
225
+ const raw =
226
+ entry && typeof entry === "object" && !Array.isArray(entry)
227
+ ? entry.value
228
+ : entry;
229
+ if (typeof raw === "boolean") {
230
+ return raw ? "TRUE" : "FALSE";
231
+ }
232
+ return typeof raw === "string" ? raw : undefined;
233
+ }
234
+
235
+ /**
236
+ * Resolve the configure presets of a set of presets documents.
237
+ *
238
+ * Inheritance follows CMake: a preset's own fields win, then those of its
239
+ * `inherits` entries in order (the first wins), recursively; `cacheVariables`
240
+ * and `environment` merge key by key the same way, and a `null` entry unsets
241
+ * the key. `name`, `hidden`, `inherits`, `description` and `displayName` are
242
+ * not inherited. A preset that is part of an inheritance cycle, or inherits
243
+ * one that does not exist, is dropped.
244
+ *
245
+ * @param {Array<{file: string, fileDir: string, document: Object}>} documents
246
+ * Parsed documents in reading order (`CMakePresets.json` first, then its
247
+ * includes, then `CMakeUserPresets.json`)
248
+ * @param {Object} context `sourceDir`, `hostSystemName`, `pathListSep`, and
249
+ * `penv` (a function reading the process environment)
250
+ * @returns {Object[]} Visible configure presets: `name`, `displayName`,
251
+ * `file`, `inherits`, `generator`, `binaryDir` (absolute), `toolchainFile`,
252
+ * `cacheVariables` (expanded strings), `environment` (expanded strings),
253
+ * `hasCondition`, and `conditionMet` (true, false or undefined)
254
+ */
255
+ export function resolveConfigurePresets(documents, context = {}) {
256
+ const byName = new Map();
257
+ for (const doc of documents || []) {
258
+ for (const preset of doc?.document?.configurePresets || []) {
259
+ if (!byName.has(preset.name)) {
260
+ byName.set(preset.name, { preset, doc });
261
+ }
262
+ }
263
+ }
264
+ const merged = new Map();
265
+ const merging = new Set();
266
+ const mergedOf = (name, depth) => {
267
+ if (merged.has(name)) {
268
+ return merged.get(name);
269
+ }
270
+ const entry = byName.get(name);
271
+ if (!entry || merging.has(name) || depth > MAX_INHERITANCE_DEPTH) {
272
+ return null;
273
+ }
274
+ merging.add(name);
275
+ const own = entry.preset;
276
+ const parents =
277
+ typeof own.inherits === "string"
278
+ ? [own.inherits]
279
+ : Array.isArray(own.inherits)
280
+ ? own.inherits.filter((p) => typeof p === "string")
281
+ : [];
282
+ const result = {};
283
+ for (const [field, value] of Object.entries(own)) {
284
+ if (MAP_FIELDS.has(field)) {
285
+ if (value && typeof value === "object" && !Array.isArray(value)) {
286
+ result[field] = { ...value };
287
+ }
288
+ } else {
289
+ result[field] = value;
290
+ }
291
+ }
292
+ let broken = false;
293
+ for (const parentName of parents) {
294
+ const parent = mergedOf(parentName, depth + 1);
295
+ if (!parent) {
296
+ broken = true;
297
+ break;
298
+ }
299
+ for (const [field, value] of Object.entries(parent.fields)) {
300
+ if (NOT_INHERITED.has(field)) {
301
+ continue;
302
+ }
303
+ if (MAP_FIELDS.has(field)) {
304
+ result[field] = { ...value, ...(result[field] || {}) };
305
+ } else if (result[field] === undefined) {
306
+ result[field] = value;
307
+ }
308
+ }
309
+ }
310
+ merging.delete(name);
311
+ const resolved = broken ? null : { fields: result, doc: entry.doc };
312
+ merged.set(name, resolved);
313
+ return resolved;
314
+ };
315
+ const presets = [];
316
+ for (const name of byName.keys()) {
317
+ const resolved = mergedOf(name, 0);
318
+ if (!resolved || resolved.fields.hidden === true) {
319
+ continue;
320
+ }
321
+ presets.push(expandPreset(name, resolved, context));
322
+ }
323
+ return presets;
324
+ }
325
+
326
+ function expandPreset(name, resolved, context) {
327
+ const { fields, doc } = resolved;
328
+ const sourceDir = context.sourceDir || "";
329
+ const generator =
330
+ typeof fields.generator === "string" ? fields.generator : "";
331
+ const base = {
332
+ sourceDir,
333
+ sourceParentDir: context.sourceParentDir ?? "",
334
+ sourceDirName: context.sourceDirName ?? "",
335
+ hostSystemName: context.hostSystemName ?? "",
336
+ pathListSep: context.pathListSep ?? ":",
337
+ presetName: name,
338
+ generator,
339
+ fileDir: doc?.fileDir ?? sourceDir,
340
+ penv: context.penv,
341
+ };
342
+ // An environment entry may refer to the process environment and to the
343
+ // other entries; a few rounds settle any chain a real preset writes.
344
+ const rawEnvironment = {};
345
+ for (const [key, value] of Object.entries(fields.environment || {})) {
346
+ if (typeof value === "string") {
347
+ rawEnvironment[key] = value;
348
+ }
349
+ }
350
+ let environment = { ...rawEnvironment };
351
+ for (let round = 0; round < 4; round++) {
352
+ const next = {};
353
+ for (const [key, value] of Object.entries(rawEnvironment)) {
354
+ next[key] = expandPresetMacros(value, {
355
+ ...base,
356
+ env: { ...environment, [key]: base.penv ? (base.penv(key) ?? "") : "" },
357
+ });
358
+ }
359
+ environment = next;
360
+ }
361
+ const expandContext = { ...base, env: environment };
362
+ const expand = (v) => expandPresetMacros(v, expandContext);
363
+ const cacheVariables = {};
364
+ for (const [key, entry] of Object.entries(fields.cacheVariables || {})) {
365
+ const value = cacheValue(entry);
366
+ if (typeof value === "string") {
367
+ cacheVariables[key] = expand(value);
368
+ }
369
+ }
370
+ let binaryDir;
371
+ if (typeof fields.binaryDir === "string" && fields.binaryDir.length) {
372
+ const dir = expand(fields.binaryDir);
373
+ binaryDir =
374
+ isAbsolute(dir) || !sourceDir ? normalize(dir) : join(sourceDir, dir);
375
+ }
376
+ const toolchainFile =
377
+ typeof fields.toolchainFile === "string" && fields.toolchainFile.length
378
+ ? expand(fields.toolchainFile)
379
+ : cacheVariables.CMAKE_TOOLCHAIN_FILE;
380
+ const inherits =
381
+ typeof fields.inherits === "string"
382
+ ? [fields.inherits]
383
+ : Array.isArray(fields.inherits)
384
+ ? fields.inherits.filter((p) => typeof p === "string")
385
+ : [];
386
+ return {
387
+ name,
388
+ displayName:
389
+ typeof fields.displayName === "string" ? fields.displayName : undefined,
390
+ file: doc?.file,
391
+ inherits,
392
+ generator: generator || undefined,
393
+ binaryDir,
394
+ toolchainFile: toolchainFile || undefined,
395
+ cacheVariables,
396
+ environment,
397
+ hasCondition: fields.condition !== undefined && fields.condition !== null,
398
+ conditionMet: evaluatePresetCondition(fields.condition, expand),
399
+ };
400
+ }