semantifold 0.9.0 → 0.11.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 (198) hide show
  1. package/README.md +6 -3
  2. package/bin/semantifold.js +6 -0
  3. package/build/bin/semantifold.d.ts +3 -0
  4. package/build/bin/semantifold.d.ts.map +1 -0
  5. package/build/bin/semantifold.js +5 -0
  6. package/build/index.d.ts +8 -0
  7. package/build/index.d.ts.map +1 -1
  8. package/build/index.js +9 -1
  9. package/build/src/artifact-path.d.ts +16 -0
  10. package/build/src/artifact-path.d.ts.map +1 -1
  11. package/build/src/artifact-path.js +29 -3
  12. package/build/src/backends/c-check.d.ts +7 -0
  13. package/build/src/backends/c-check.d.ts.map +1 -0
  14. package/build/src/backends/c-check.js +65 -0
  15. package/build/src/backends/check-plan.d.ts +96 -0
  16. package/build/src/backends/check-plan.d.ts.map +1 -0
  17. package/build/src/backends/check-plan.js +135 -0
  18. package/build/src/backends/cpp-check.d.ts +7 -0
  19. package/build/src/backends/cpp-check.d.ts.map +1 -0
  20. package/build/src/backends/cpp-check.js +59 -0
  21. package/build/src/backends/csharp-check.d.ts +7 -0
  22. package/build/src/backends/csharp-check.d.ts.map +1 -0
  23. package/build/src/backends/csharp-check.js +125 -0
  24. package/build/src/backends/csharp.d.ts +1 -0
  25. package/build/src/backends/csharp.d.ts.map +1 -1
  26. package/build/src/backends/csharp.js +5 -4
  27. package/build/src/backends/dart-check.d.ts +7 -0
  28. package/build/src/backends/dart-check.d.ts.map +1 -0
  29. package/build/src/backends/dart-check.js +103 -0
  30. package/build/src/backends/dart.d.ts +2 -0
  31. package/build/src/backends/dart.d.ts.map +1 -1
  32. package/build/src/backends/dart.js +5 -5
  33. package/build/src/backends/go-check.d.ts +7 -0
  34. package/build/src/backends/go-check.d.ts.map +1 -0
  35. package/build/src/backends/go-check.js +77 -0
  36. package/build/src/backends/go.d.ts +1 -0
  37. package/build/src/backends/go.d.ts.map +1 -1
  38. package/build/src/backends/go.js +3 -3
  39. package/build/src/backends/java-check.d.ts +21 -0
  40. package/build/src/backends/java-check.d.ts.map +1 -0
  41. package/build/src/backends/java-check.js +73 -0
  42. package/build/src/backends/javascript-check.d.ts +7 -0
  43. package/build/src/backends/javascript-check.d.ts.map +1 -0
  44. package/build/src/backends/javascript-check.js +29 -0
  45. package/build/src/backends/kotlin-check.d.ts +7 -0
  46. package/build/src/backends/kotlin-check.d.ts.map +1 -0
  47. package/build/src/backends/kotlin-check.js +31 -0
  48. package/build/src/backends/kotlin.d.ts +1 -1
  49. package/build/src/backends/kotlin.js +2 -2
  50. package/build/src/backends/php-check.d.ts +7 -0
  51. package/build/src/backends/php-check.d.ts.map +1 -0
  52. package/build/src/backends/php-check.js +21 -0
  53. package/build/src/backends/program.d.ts +7 -0
  54. package/build/src/backends/program.d.ts.map +1 -1
  55. package/build/src/backends/program.js +16 -1
  56. package/build/src/backends/python-check.d.ts +7 -0
  57. package/build/src/backends/python-check.d.ts.map +1 -0
  58. package/build/src/backends/python-check.js +28 -0
  59. package/build/src/backends/ruby-check.d.ts +7 -0
  60. package/build/src/backends/ruby-check.d.ts.map +1 -0
  61. package/build/src/backends/ruby-check.js +21 -0
  62. package/build/src/backends/rust-check.d.ts +7 -0
  63. package/build/src/backends/rust-check.d.ts.map +1 -0
  64. package/build/src/backends/rust-check.js +65 -0
  65. package/build/src/backends/shared.d.ts.map +1 -1
  66. package/build/src/backends/shared.js +29 -1
  67. package/build/src/backends/swift-check.d.ts +7 -0
  68. package/build/src/backends/swift-check.d.ts.map +1 -0
  69. package/build/src/backends/swift-check.js +77 -0
  70. package/build/src/backends/typescript-check.d.ts +7 -0
  71. package/build/src/backends/typescript-check.d.ts.map +1 -0
  72. package/build/src/backends/typescript-check.js +33 -0
  73. package/build/src/backends/zig-check.d.ts +7 -0
  74. package/build/src/backends/zig-check.d.ts.map +1 -0
  75. package/build/src/backends/zig-check.js +70 -0
  76. package/build/src/diagnostic.d.ts +13 -1
  77. package/build/src/diagnostic.d.ts.map +1 -1
  78. package/build/src/diagnostic.js +14 -2
  79. package/build/src/frontends/java.d.ts.map +1 -1
  80. package/build/src/frontends/java.js +23 -1
  81. package/build/src/frontends/javascript-typescript.d.ts.map +1 -1
  82. package/build/src/frontends/javascript-typescript.js +45 -4
  83. package/build/src/frontends/php.d.ts.map +1 -1
  84. package/build/src/frontends/php.js +54 -3
  85. package/build/src/frontends/program.d.ts +6 -0
  86. package/build/src/frontends/program.d.ts.map +1 -1
  87. package/build/src/frontends/program.js +9 -1
  88. package/build/src/frontends/ruby.d.ts.map +1 -1
  89. package/build/src/frontends/ruby.js +55 -5
  90. package/build/src/language-registry.d.ts +54 -0
  91. package/build/src/language-registry.d.ts.map +1 -1
  92. package/build/src/language-registry.js +124 -10
  93. package/build/src/project-build.d.ts +172 -0
  94. package/build/src/project-build.d.ts.map +1 -0
  95. package/build/src/project-build.js +320 -0
  96. package/build/src/project-cli.d.ts +40 -0
  97. package/build/src/project-cli.d.ts.map +1 -0
  98. package/build/src/project-cli.js +145 -0
  99. package/build/src/project-manifest.d.ts +148 -0
  100. package/build/src/project-manifest.d.ts.map +1 -0
  101. package/build/src/project-manifest.js +432 -0
  102. package/build/src/project-reporter.d.ts +81 -0
  103. package/build/src/project-reporter.d.ts.map +1 -0
  104. package/build/src/project-reporter.js +293 -0
  105. package/build/src/project-snapshot.d.ts +129 -0
  106. package/build/src/project-snapshot.d.ts.map +1 -0
  107. package/build/src/project-snapshot.js +362 -0
  108. package/build/src/project-watch-reporter.d.ts +125 -0
  109. package/build/src/project-watch-reporter.d.ts.map +1 -0
  110. package/build/src/project-watch-reporter.js +280 -0
  111. package/build/src/project-watch.d.ts +133 -0
  112. package/build/src/project-watch.d.ts.map +1 -0
  113. package/build/src/project-watch.js +839 -0
  114. package/build/src/publication.d.ts +69 -5
  115. package/build/src/publication.d.ts.map +1 -1
  116. package/build/src/publication.js +246 -57
  117. package/build/src/semantic/effects.js +3 -1
  118. package/build/src/semantic/provenance.d.ts.map +1 -1
  119. package/build/src/semantic/provenance.js +11 -1
  120. package/build/src/semantic/types.d.ts +355 -4
  121. package/build/src/semantic/types.d.ts.map +1 -1
  122. package/build/src/semantic/types.js +92 -3
  123. package/build/src/semantic/validate.js +18 -1
  124. package/build/src/subprocess.d.ts +8 -0
  125. package/build/src/subprocess.d.ts.map +1 -1
  126. package/build/src/subprocess.js +50 -9
  127. package/build/src/target-check.d.ts +52 -0
  128. package/build/src/target-check.d.ts.map +1 -0
  129. package/build/src/target-check.js +796 -0
  130. package/build/src/toolchains.d.ts.map +1 -1
  131. package/build/src/toolchains.js +3 -3
  132. package/docs/adr-expression-breadth.md +186 -0
  133. package/docs/architecture.md +3 -1
  134. package/docs/c.md +4 -0
  135. package/docs/cpp.md +4 -0
  136. package/docs/dart.md +4 -0
  137. package/docs/generated-artifact-publication.md +11 -8
  138. package/docs/kotlin.md +2 -2
  139. package/docs/language-support.md +40 -6
  140. package/docs/parser-qualification.md +1 -1
  141. package/docs/project-build-cli.md +147 -0
  142. package/docs/project-watch.md +60 -0
  143. package/docs/rust.md +4 -0
  144. package/docs/swift.md +2 -0
  145. package/docs/testing.md +70 -3
  146. package/docs/watch-build-pipeline.md +39 -23
  147. package/docs/zig.md +2 -0
  148. package/examples/jsdoc-java-watch/expected-output.txt +3 -0
  149. package/examples/jsdoc-java-watch/semantifold.json +23 -0
  150. package/examples/jsdoc-java-watch/src/main.js +21 -0
  151. package/index.js +8 -0
  152. package/package.json +6 -1
  153. package/src/artifact-path.js +31 -2
  154. package/src/backends/c-check.js +80 -0
  155. package/src/backends/check-plan.js +147 -0
  156. package/src/backends/cpp-check.js +73 -0
  157. package/src/backends/csharp-check.js +139 -0
  158. package/src/backends/csharp.js +4 -3
  159. package/src/backends/dart-check.js +117 -0
  160. package/src/backends/dart.js +4 -4
  161. package/src/backends/go-check.js +89 -0
  162. package/src/backends/go.js +2 -2
  163. package/src/backends/java-check.js +77 -0
  164. package/src/backends/javascript-check.js +33 -0
  165. package/src/backends/kotlin-check.js +41 -0
  166. package/src/backends/kotlin.js +1 -1
  167. package/src/backends/php-check.js +23 -0
  168. package/src/backends/program.js +17 -0
  169. package/src/backends/python-check.js +30 -0
  170. package/src/backends/ruby-check.js +23 -0
  171. package/src/backends/rust-check.js +78 -0
  172. package/src/backends/shared.js +30 -0
  173. package/src/backends/swift-check.js +89 -0
  174. package/src/backends/typescript-check.js +37 -0
  175. package/src/backends/zig-check.js +81 -0
  176. package/src/diagnostic.js +9 -1
  177. package/src/frontends/java.js +24 -0
  178. package/src/frontends/javascript-typescript.js +49 -2
  179. package/src/frontends/php.js +61 -2
  180. package/src/frontends/program.js +9 -0
  181. package/src/frontends/ruby.js +62 -2
  182. package/src/language-registry.js +130 -9
  183. package/src/project-build.js +353 -0
  184. package/src/project-cli.js +155 -0
  185. package/src/project-manifest.js +479 -0
  186. package/src/project-reporter.js +320 -0
  187. package/src/project-snapshot.js +403 -0
  188. package/src/project-watch-reporter.js +303 -0
  189. package/src/project-watch.js +870 -0
  190. package/src/publication.js +275 -58
  191. package/src/semantic/effects.js +1 -0
  192. package/src/semantic/provenance.js +8 -0
  193. package/src/semantic/types.js +101 -2
  194. package/src/semantic/validate.js +26 -0
  195. package/src/subprocess.js +49 -8
  196. package/src/target-check.js +844 -0
  197. package/src/toolchains.js +3 -2
  198. package/tsconfig.json +1 -1
@@ -0,0 +1,139 @@
1
+ // @ts-check
2
+
3
+ import {createHash} from "node:crypto"
4
+ import path from "node:path"
5
+ import {SemantifoldDiagnostic} from "../diagnostic.js"
6
+ import {
7
+ checkArtifacts,
8
+ checkOutput,
9
+ checkPlan,
10
+ checkStage,
11
+ checkTool,
12
+ environmentPath,
13
+ pathArgument
14
+ } from "./check-plan.js"
15
+ import {csharpProjectManifest} from "./csharp.js"
16
+
17
+ /**
18
+ * Constructs C#'s offline restore and non-executing build plan.
19
+ * @param {import("../language-registry.js").TargetCheckPlanContext} context - Validated candidate context.
20
+ * @returns {import("../semantic/types.js").TargetCheckPlan} Immutable C# plan.
21
+ */
22
+ export function createCSharpCheckPlan(context) {
23
+ const tool = checkTool(context, "dotnet", "csharp")
24
+ const artifacts = checkArtifacts(context, artifact => artifact.path.endsWith(".cs") ||
25
+ artifact.path == "Semantifold.csproj" || artifact.path == "packages.lock.json",
26
+ "csharp", "only staged C# source and canonical project/lock artifacts")
27
+ const projects = context.artifacts.artifacts.filter(artifact => artifact.path == "Semantifold.csproj")
28
+ const sources = artifacts.filter(artifact => artifact.endsWith(".cs"))
29
+
30
+ if (projects.length != 1 || projects[0].contentKind != "text" || projects[0].role != "manifest" ||
31
+ projects[0].content != csharpProjectManifest) {
32
+ throw new SemantifoldDiagnostic({
33
+ code: "INVALID_TARGET_CHECK_PLAN",
34
+ language: "csharp",
35
+ message: "C# developer checks require the exact producer-owned 'Semantifold.csproj' artifact."
36
+ })
37
+ }
38
+ if (sources.length == 0) {
39
+ throw new SemantifoldDiagnostic({
40
+ code: "INVALID_TARGET_CHECK_PLAN",
41
+ language: "csharp",
42
+ message: "C# developer checks require at least one staged '.cs' artifact."
43
+ })
44
+ }
45
+ const restoreArtifacts = context.artifacts.artifacts
46
+ .filter(artifact => artifact.path == "Semantifold.csproj" || artifact.path == "packages.lock.json")
47
+ .sort((left, right) => left.path.localeCompare(right.path, "en"))
48
+ const restoreInputs = Object.freeze(restoreArtifacts.map(artifact => path.join(context.sourcePath, artifact.path)))
49
+ const restoreHash = createHash("sha256")
50
+
51
+ for (const artifact of restoreArtifacts) {
52
+ const contentLength = typeof artifact.content == "string" ? Buffer.byteLength(artifact.content) : artifact.content.byteLength
53
+
54
+ restoreHash.update(`${Buffer.byteLength(artifact.path)}:`).update(artifact.path)
55
+ .update(`${contentLength}:`).update(artifact.content)
56
+ }
57
+ const inputHash = restoreHash.digest("hex")
58
+ const projectPath = path.join(context.sourcePath, projects[0].path)
59
+ const packages = path.join(context.buildPath, "nuget-packages")
60
+ const intermediatePath = path.join(context.buildPath, "obj")
61
+ const intermediate = `${intermediatePath}/`
62
+ const output = path.join(context.buildPath, "bin")
63
+ const compileItems = sources.map(source => path.relative(context.sourcePath, source).split(path.sep).join("/")).join("%3B")
64
+ const isolatedProjectProperties = [
65
+ "--property:ImportDirectoryBuildProps=false",
66
+ "--property:ImportDirectoryBuildTargets=false"
67
+ ]
68
+ const restoreArgv = [
69
+ "restore", projectPath, "--source", context.sourcePath, "--packages", packages, "--no-cache", "--force",
70
+ "--disable-parallel",
71
+ ...(restoreArtifacts.some(artifact => artifact.path == "packages.lock.json") ? ["--locked-mode"] : []),
72
+ "--nologo", ...isolatedProjectProperties, `--property:BaseIntermediateOutputPath=${intermediate}`,
73
+ `--property:MSBuildProjectExtensionsPath=${intermediate}`
74
+ ]
75
+ const compileArgv = [
76
+ "build", projectPath, "--configuration", "Release", "--no-restore", "--nologo", "--warnaserror",
77
+ "--disable-build-servers", "--output", output, ...isolatedProjectProperties,
78
+ `--property:SemantifoldCompileItems=${compileItems}`, "--property:UseSharedCompilation=false",
79
+ `--property:BaseIntermediateOutputPath=${intermediate}`,
80
+ `--property:MSBuildProjectExtensionsPath=${intermediate}`
81
+ ]
82
+ const environment = {
83
+ DOTNET_CLI_HOME: path.join(context.buildPath, "dotnet-home"),
84
+ DOTNET_CLI_TELEMETRY_OPTOUT: "1",
85
+ DOTNET_CLI_USE_MSBUILD_SERVER: "0",
86
+ DOTNET_CLI_WORKLOAD_UPDATE_NOTIFY_DISABLE: "1",
87
+ DOTNET_NOLOGO: "1",
88
+ DOTNET_SKIP_FIRST_TIME_EXPERIENCE: "1",
89
+ DOTNET_SYSTEM_GLOBALIZATION_INVARIANT: "1",
90
+ HOME: path.join(context.buildPath, "home"),
91
+ NUGET_HTTP_CACHE_PATH: path.join(context.buildPath, "nuget-http-cache"),
92
+ NUGET_PACKAGES: packages,
93
+ NUGET_PLUGINS_CACHE_PATH: path.join(context.buildPath, "nuget-plugins-cache"),
94
+ TMPDIR: path.join(context.buildPath, "tmp"),
95
+ XDG_CACHE_HOME: path.join(context.buildPath, "cache")
96
+ }
97
+ const environmentPaths = [
98
+ environmentPath("DOTNET_CLI_HOME", "build"), environmentPath("HOME", "build"),
99
+ environmentPath("NUGET_HTTP_CACHE_PATH", "build"), environmentPath("NUGET_PACKAGES", "build"),
100
+ environmentPath("NUGET_PLUGINS_CACHE_PATH", "build"), environmentPath("TMPDIR", "build"),
101
+ environmentPath("XDG_CACHE_HOME", "build")
102
+ ]
103
+ const ownedOutput = checkOutput(context.buildPath, "application/octet-stream", "compiler-output")
104
+ const restore = checkStage({
105
+ argv: restoreArgv,
106
+ cwd: context.sourcePath,
107
+ environment,
108
+ environmentPaths,
109
+ inputHash,
110
+ inputs: restoreInputs,
111
+ output: null,
112
+ pathArguments: [
113
+ pathArgument(1, "source"), pathArgument(3, "source"), pathArgument(5, "build"),
114
+ pathArgument(restoreArgv.length - 2, "build", "--property:BaseIntermediateOutputPath="),
115
+ pathArgument(restoreArgv.length - 1, "build", "--property:MSBuildProjectExtensionsPath=")
116
+ ],
117
+ stage: "restore",
118
+ tool,
119
+ transientPaths: [intermediatePath]
120
+ })
121
+ const compile = checkStage({
122
+ argv: compileArgv,
123
+ cwd: context.sourcePath,
124
+ environment,
125
+ environmentPaths,
126
+ inputs: artifacts,
127
+ output: ownedOutput,
128
+ pathArguments: [
129
+ pathArgument(1, "source"), pathArgument(9, "build"),
130
+ pathArgument(compileArgv.length - 2, "build", "--property:BaseIntermediateOutputPath="),
131
+ pathArgument(compileArgv.length - 1, "build", "--property:MSBuildProjectExtensionsPath=")
132
+ ],
133
+ stage: "compile",
134
+ tool,
135
+ transientPaths: [intermediatePath]
136
+ })
137
+
138
+ return checkPlan(context, "csharp", artifacts, [restore, compile])
139
+ }
@@ -6,7 +6,7 @@ import {validateBackendModule, emitExpression} from "./shared.js"
6
6
  import {emitScalarType} from "./scalars.js"
7
7
  import {SourceWriter} from "./writer.js"
8
8
 
9
- const project = `<Project Sdk="Microsoft.NET.Sdk">
9
+ export const csharpProjectManifest = `<Project Sdk="Microsoft.NET.Sdk">
10
10
  <PropertyGroup>
11
11
  <OutputType>Exe</OutputType>
12
12
  <TargetFramework>net10.0</TargetFramework>
@@ -25,13 +25,14 @@ const project = `<Project Sdk="Microsoft.NET.Sdk">
25
25
  <DebugType>none</DebugType>
26
26
  <UseAppHost>false</UseAppHost>
27
27
  <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
28
+ <SemantifoldCompileItems Condition="'$(SemantifoldCompileItems)' == ''">Program.cs</SemantifoldCompileItems>
28
29
  <AssemblyName>Semantifold</AssemblyName>
29
30
  <RootNamespace>Semantifold.Generated</RootNamespace>
30
31
  <StartupObject>Semantifold.Generated.Program</StartupObject>
31
32
  <PathMap>$(MSBuildProjectDirectory)=/_/</PathMap>
32
33
  </PropertyGroup>
33
34
  <ItemGroup>
34
- <Compile Include="Program.cs" />
35
+ <Compile Include="$(SemantifoldCompileItems)" />
35
36
  </ItemGroup>
36
37
  </Project>
37
38
  `
@@ -66,7 +67,7 @@ export function generateCSharpProject({filename, mapDirective, module, sourceMap
66
67
  provenance: {kind: "text", mapping, sourceMap: toSourceMapV3(mapping)},
67
68
  role: "entry"
68
69
  }, {
69
- content: project,
70
+ content: csharpProjectManifest,
70
71
  contentKind: "text",
71
72
  mediaType: "application/xml",
72
73
  ownership: "generated",
@@ -0,0 +1,117 @@
1
+ // @ts-check
2
+
3
+ import {createHash} from "node:crypto"
4
+ import path from "node:path"
5
+ import {SemantifoldDiagnostic} from "../diagnostic.js"
6
+ import {
7
+ checkArtifacts,
8
+ checkPlan,
9
+ checkStage,
10
+ checkTool,
11
+ environmentPath,
12
+ pathArgument
13
+ } from "./check-plan.js"
14
+ import {dartLockfile, dartPubspec} from "./dart.js"
15
+
16
+ /**
17
+ * Constructs Dart's offline package verification, native compile, format and analysis plan.
18
+ * @param {import("../language-registry.js").TargetCheckPlanContext} context - Validated candidate context.
19
+ * @returns {import("../semantic/types.js").TargetCheckPlan} Immutable Dart plan.
20
+ */
21
+ export function createDartCheckPlan(context) {
22
+ const tool = checkTool(context, "dart", "dart")
23
+ const artifacts = checkArtifacts(context, artifact => artifact.path.endsWith(".dart") ||
24
+ artifact.path == "pubspec.yaml" || artifact.path == "pubspec.lock",
25
+ "dart", "only staged Dart source and canonical pub package/lock artifacts")
26
+ const pubspecs = context.artifacts.artifacts.filter(artifact => artifact.path == "pubspec.yaml")
27
+ const lockfiles = context.artifacts.artifacts.filter(artifact => artifact.path == "pubspec.lock")
28
+ const sources = artifacts.filter(artifact => artifact.endsWith(".dart"))
29
+
30
+ if (pubspecs.length != 1 || pubspecs[0].contentKind != "text" || pubspecs[0].role != "manifest" ||
31
+ pubspecs[0].content != dartPubspec || lockfiles.length != 1 || lockfiles[0].contentKind != "text" ||
32
+ lockfiles[0].role != "manifest" || lockfiles[0].content != dartLockfile || artifacts.length != 3 || sources.length != 1 ||
33
+ sources[0] != path.join(context.sourcePath, "bin/program.dart")) {
34
+ throw new SemantifoldDiagnostic({
35
+ code: "INVALID_TARGET_CHECK_PLAN",
36
+ language: "dart",
37
+ message: "Dart developer checks require the exact dependency-free pub package/lock and staged '.dart' source."
38
+ })
39
+ }
40
+ const restoreArtifacts = context.artifacts.artifacts.filter(artifact =>
41
+ artifact.path == "pubspec.yaml" || artifact.path == "pubspec.lock").sort((left, right) => left.path.localeCompare(right.path, "en"))
42
+ const restoreInputs = Object.freeze(restoreArtifacts.map(artifact => path.join(context.sourcePath, artifact.path)))
43
+ const restoreHash = createHash("sha256")
44
+
45
+ for (const artifact of restoreArtifacts) {
46
+ const contentLength = typeof artifact.content == "string" ? Buffer.byteLength(artifact.content) : artifact.content.byteLength
47
+
48
+ restoreHash.update(`${Buffer.byteLength(artifact.path)}:`).update(artifact.path)
49
+ .update(`${contentLength}:`).update(artifact.content)
50
+ }
51
+ const home = path.join(context.buildPath, "home")
52
+ const pubCache = path.join(context.buildPath, "pub-cache")
53
+ const temporary = path.join(context.buildPath, "tmp")
54
+ const environment = {
55
+ CI: "true",
56
+ DART_SUPPRESS_ANALYTICS: "true",
57
+ HOME: home,
58
+ PUB_CACHE: pubCache,
59
+ PUB_HOSTED_URL: "http://127.0.0.1:9",
60
+ TMPDIR: temporary
61
+ }
62
+ const environmentPaths = [environmentPath("HOME", "build"), environmentPath("PUB_CACHE", "build"),
63
+ environmentPath("TMPDIR", "build")]
64
+ const nativeOutput = path.join(context.buildPath, "native-output")
65
+ const binary = path.join(nativeOutput, "semantifold-dart")
66
+ const compileArgv = ["compile", "exe", sources[0], "-o", binary]
67
+
68
+ return checkPlan(context, "dart", artifacts, [
69
+ checkStage({
70
+ argv: ["pub", "get", "--offline", "--dry-run", "--enforce-lockfile", "--no-precompile"],
71
+ cwd: context.sourcePath,
72
+ environment,
73
+ environmentPaths,
74
+ inputHash: restoreHash.digest("hex"),
75
+ inputs: restoreInputs,
76
+ output: null,
77
+ pathArguments: [],
78
+ stage: "restore",
79
+ tool,
80
+ transientPaths: [path.join(context.sourcePath, ".dart_tool")]
81
+ }),
82
+ checkStage({
83
+ argv: compileArgv,
84
+ cwd: context.sourcePath,
85
+ environment,
86
+ environmentPaths,
87
+ inputs: artifacts,
88
+ output: null,
89
+ pathArguments: [pathArgument(2, "source"), pathArgument(4, "build")],
90
+ stage: "compile",
91
+ tool,
92
+ transientPaths: [nativeOutput]
93
+ }),
94
+ checkStage({
95
+ argv: ["format", "--output=none", "--set-exit-if-changed", sources[0]],
96
+ cwd: context.sourcePath,
97
+ environment,
98
+ environmentPaths,
99
+ inputs: sources,
100
+ output: null,
101
+ pathArguments: [pathArgument(3, "source")],
102
+ stage: "validate",
103
+ tool
104
+ }),
105
+ checkStage({
106
+ argv: ["analyze", "--fatal-infos", "--fatal-warnings", context.sourcePath],
107
+ cwd: context.sourcePath,
108
+ environment,
109
+ environmentPaths,
110
+ inputs: artifacts,
111
+ output: null,
112
+ pathArguments: [pathArgument(3, "source")],
113
+ stage: "validate",
114
+ tool
115
+ })
116
+ ])
117
+ }
@@ -7,8 +7,8 @@ import {dartRuntime} from "./dart-runtime.js"
7
7
  import {emitScalarType} from "./scalars.js"
8
8
  import {SourceWriter} from "./writer.js"
9
9
 
10
- const pubspec = "name: semantifold_generated\npublish_to: none\nenvironment:\n sdk: 3.13.3\n"
11
- const lockfile = "# Generated by pub\n# See https://dart.dev/tools/pub/glossary#lockfile\npackages: {}\nsdks:\n dart: \"3.13.3\"\n"
10
+ export const dartPubspec = "name: semantifold_generated\npublish_to: none\nenvironment:\n sdk: 3.13.3\n"
11
+ export const dartLockfile = "# Generated by pub\n# See https://dart.dev/tools/pub/glossary#lockfile\npackages: {}\nsdks:\n dart: \"3.13.3\"\n"
12
12
 
13
13
  /**
14
14
  * Emits one deterministic dependency-free Dart package candidate.
@@ -35,7 +35,7 @@ export function generateDartPackage({filename, mapDirective, module, sourceMapFi
35
35
 
36
36
  return {
37
37
  artifacts: [{
38
- content: pubspec,
38
+ content: dartPubspec,
39
39
  contentKind: "text",
40
40
  mediaType: "application/yaml",
41
41
  ownership: "generated",
@@ -47,7 +47,7 @@ export function generateDartPackage({filename, mapDirective, module, sourceMapFi
47
47
  },
48
48
  role: "manifest"
49
49
  }, {
50
- content: lockfile,
50
+ content: dartLockfile,
51
51
  contentKind: "text",
52
52
  mediaType: "application/yaml",
53
53
  ownership: "generated",
@@ -0,0 +1,89 @@
1
+ // @ts-check
2
+
3
+ import path from "node:path"
4
+ import {SemantifoldDiagnostic} from "../diagnostic.js"
5
+ import {
6
+ checkArtifacts,
7
+ checkOutput,
8
+ checkPlan,
9
+ checkStage,
10
+ checkTool,
11
+ environmentPath,
12
+ pathArgument
13
+ } from "./check-plan.js"
14
+ import {goModuleManifest} from "./go.js"
15
+
16
+ /**
17
+ * Constructs Go's cgo-disabled, offline build/vet plan.
18
+ * @param {import("../language-registry.js").TargetCheckPlanContext} context - Validated candidate context.
19
+ * @returns {import("../semantic/types.js").TargetCheckPlan} Immutable Go plan.
20
+ */
21
+ export function createGoCheckPlan(context) {
22
+ const tool = checkTool(context, "go", "go")
23
+ const artifacts = checkArtifacts(context, artifact => artifact.path.endsWith(".go") || artifact.path == "go.mod",
24
+ "go", "only staged '.go' sources and the canonical module manifest")
25
+ const manifests = context.artifacts.artifacts.filter(artifact => artifact.path == "go.mod")
26
+ const sources = artifacts.filter(artifact => artifact.endsWith(".go"))
27
+
28
+ if (manifests.length != 1 || manifests[0].contentKind != "text" || manifests[0].role != "manifest" ||
29
+ manifests[0].content != goModuleManifest || artifacts.length != 2 || sources.length != 1 ||
30
+ sources[0] != path.join(context.sourcePath, "main.go")) {
31
+ throw new SemantifoldDiagnostic({
32
+ code: "INVALID_TARGET_CHECK_PLAN",
33
+ language: "go",
34
+ message: "Go developer checks require the exact dependency-free 'go.mod' and at least one staged '.go' source."
35
+ })
36
+ }
37
+ const cache = path.join(context.buildPath, "go-cache")
38
+ const moduleCache = path.join(context.buildPath, "go-mod-cache")
39
+ const goPath = path.join(context.buildPath, "go-path")
40
+ const temporary = path.join(context.buildPath, "go-tmp")
41
+ const home = path.join(context.buildPath, "go-home")
42
+ const binary = path.join(context.buildPath, "semantifold-go")
43
+ const environment = {
44
+ CGO_ENABLED: "0",
45
+ GOARCH: "amd64",
46
+ GOCACHE: cache,
47
+ GOENV: "off",
48
+ GOMODCACHE: moduleCache,
49
+ GOOS: "linux",
50
+ GOPATH: goPath,
51
+ GOPROXY: "off",
52
+ GOSUMDB: "off",
53
+ GOTOOLCHAIN: "local",
54
+ GOTMPDIR: temporary,
55
+ GOVCS: "off",
56
+ GOWORK: "off",
57
+ GO_TELEMETRY_CHILD: "2",
58
+ HOME: home
59
+ }
60
+ const environmentPaths = [
61
+ environmentPath("GOCACHE", "build"), environmentPath("GOMODCACHE", "build"), environmentPath("GOPATH", "build"),
62
+ environmentPath("GOTMPDIR", "build"), environmentPath("HOME", "build")
63
+ ]
64
+
65
+ return checkPlan(context, "go", artifacts, [
66
+ checkStage({
67
+ argv: ["build", "-mod=readonly", "-trimpath", "-buildvcs=false", "-ldflags=-buildid=", "-o", binary, "."],
68
+ cwd: context.sourcePath,
69
+ environment,
70
+ environmentPaths,
71
+ inputs: artifacts,
72
+ output: checkOutput(context.buildPath, "application/x-executable", "compiler-output"),
73
+ pathArguments: [pathArgument(6, "build")],
74
+ stage: "compile",
75
+ tool
76
+ }),
77
+ checkStage({
78
+ argv: ["vet", "-mod=readonly", "."],
79
+ cwd: context.sourcePath,
80
+ environment,
81
+ environmentPaths,
82
+ inputs: artifacts,
83
+ output: null,
84
+ pathArguments: [],
85
+ stage: "validate",
86
+ tool
87
+ })
88
+ ])
89
+ }
@@ -6,7 +6,7 @@ import {validateBackendModule, emitExpression} from "./shared.js"
6
6
  import {emitScalarType} from "./scalars.js"
7
7
  import {SourceWriter} from "./writer.js"
8
8
 
9
- const manifest = "module example.com/semantifold/generated\n\ngo 1.26.0\n"
9
+ export const goModuleManifest = "module example.com/semantifold/generated\n\ngo 1.26.0\n"
10
10
  const binarySyntax = Object.freeze({
11
11
  BooleanAnd: "&&", BooleanEqual: "==", BooleanNotEqual: "!=", BooleanOr: "||",
12
12
  IntegerAdd: "+", IntegerEqual: "==", IntegerGreaterThan: ">", IntegerGreaterThanOrEqual: ">=",
@@ -38,7 +38,7 @@ export function generateGoModule({filename, mapDirective, module, sourceMapFilen
38
38
  if (!root) throw new Error("Validated Go module omitted its canonical root provenance.")
39
39
  return {
40
40
  artifacts: [{
41
- content: manifest,
41
+ content: goModuleManifest,
42
42
  contentKind: "text",
43
43
  mediaType: "text/plain",
44
44
  ownership: "generated",
@@ -0,0 +1,77 @@
1
+ // @ts-check
2
+
3
+ import path from "node:path"
4
+ import {SemantifoldDiagnostic} from "../diagnostic.js"
5
+ import {deterministicEnvironment} from "../toolchains.js"
6
+
7
+ /**
8
+ * Constructs Java's non-executing compiler plan from staged generated artifacts.
9
+ * @param {Readonly<{
10
+ * artifacts: import("../semantic/types.js").GeneratedArtifactSet,
11
+ * buildPath: string,
12
+ * projectId: string,
13
+ * sourcePath: string,
14
+ * targetId: string,
15
+ * tools: readonly import("../semantic/types.js").DiscoveredToolchain[]
16
+ * }>} context - Exact validated candidate context.
17
+ * @returns {import("../semantic/types.js").TargetCheckPlan} Immutable javac plan.
18
+ */
19
+ export function createJavaCheckPlan(context) {
20
+ const javac = context.tools.find(({id}) => id == "javac")
21
+
22
+ if (!javac) {
23
+ throw new SemantifoldDiagnostic({
24
+ code: "INVALID_TARGET_CHECK_PLAN",
25
+ language: "java",
26
+ message: "Java developer checks require the declared 'javac' toolchain."
27
+ })
28
+ }
29
+ const artifactPaths = context.artifacts.artifacts
30
+ .filter(artifact => artifact.path.endsWith(".java"))
31
+ .map(artifact => path.join(context.sourcePath, artifact.path))
32
+
33
+ if (artifactPaths.length == 0) {
34
+ throw new SemantifoldDiagnostic({
35
+ code: "INVALID_TARGET_CHECK_PLAN",
36
+ language: "java",
37
+ message: "Java developer checks require at least one staged '.java' artifact."
38
+ })
39
+ }
40
+ const argv = Object.freeze(["-d", context.buildPath, ...artifactPaths])
41
+ const pathArguments = Object.freeze([
42
+ Object.freeze({index: 1, ownership: /** @type {const} */ ("build")}),
43
+ ...artifactPaths.map((_, index) => Object.freeze({index: index + 2, ownership: /** @type {const} */ ("source")}))
44
+ ])
45
+ const stage = Object.freeze({
46
+ argv,
47
+ cwd: context.sourcePath,
48
+ environment: deterministicEnvironment({}),
49
+ environmentPaths: Object.freeze([]),
50
+ executable: javac.executable,
51
+ inputHash: null,
52
+ inputs: Object.freeze(artifactPaths),
53
+ output: Object.freeze({
54
+ mediaType: "application/java-vm",
55
+ ownership: /** @type {const} */ ("build"),
56
+ path: context.buildPath,
57
+ role: "compiler-output"
58
+ }),
59
+ pathArguments,
60
+ stage: /** @type {const} */ ("compile"),
61
+ tool: javac,
62
+ transientPaths: Object.freeze([])
63
+ })
64
+
65
+ return Object.freeze({
66
+ artifactPaths: Object.freeze(artifactPaths),
67
+ buildPath: context.buildPath,
68
+ mode: /** @type {const} */ ("developer-check"),
69
+ projectId: context.projectId,
70
+ schema: /** @type {const} */ ("SemantifoldTargetCheckPlan"),
71
+ sourcePath: context.sourcePath,
72
+ stages: Object.freeze([stage]),
73
+ target: "java",
74
+ targetId: context.targetId,
75
+ version: /** @type {const} */ (1)
76
+ })
77
+ }
@@ -0,0 +1,33 @@
1
+ // @ts-check
2
+
3
+ import path from "node:path"
4
+ import {checkArtifacts, checkPlan, checkStage, checkTool, pathArgument} from "./check-plan.js"
5
+ import {SemantifoldDiagnostic} from "../diagnostic.js"
6
+
7
+ /**
8
+ * Constructs JavaScript's non-executing parse-check plan.
9
+ * @param {import("../language-registry.js").TargetCheckPlanContext} context - Validated candidate context.
10
+ * @returns {import("../semantic/types.js").TargetCheckPlan} Immutable JavaScript plan.
11
+ */
12
+ export function createJavaScriptCheckPlan(context) {
13
+ const tool = checkTool(context, "node", "javascript")
14
+ const artifacts = checkArtifacts(context, artifact => artifact.path.endsWith(".js") || path.basename(artifact.path) == "package.json",
15
+ "javascript", "only staged '.js' artifacts and package manifests")
16
+ const sources = artifacts.filter(artifact => artifact.endsWith(".js"))
17
+ const manifests = artifacts.filter(artifact => artifact.endsWith("package.json"))
18
+
19
+ if (sources.length == 0) {
20
+ throw new SemantifoldDiagnostic({code: "INVALID_TARGET_CHECK_PLAN", language: "javascript",
21
+ message: "JavaScript developer checks require at least one staged '.js' artifact."})
22
+ }
23
+
24
+ return checkPlan(context, "javascript", artifacts, sources.map((source, index) => checkStage({
25
+ argv: ["--check", source],
26
+ cwd: context.sourcePath,
27
+ inputs: [source, ...(index == 0 ? manifests : [])],
28
+ output: null,
29
+ pathArguments: [pathArgument(1, "source")],
30
+ stage: "validate",
31
+ tool
32
+ })))
33
+ }
@@ -0,0 +1,41 @@
1
+ // @ts-check
2
+
3
+ import path from "node:path"
4
+ import {
5
+ checkArtifacts,
6
+ checkOutput,
7
+ checkPlan,
8
+ checkStage,
9
+ checkTool,
10
+ environmentPath,
11
+ pathArgument
12
+ } from "./check-plan.js"
13
+
14
+ /**
15
+ * Constructs Kotlin/JVM's non-executing compiler plan.
16
+ * @param {import("../language-registry.js").TargetCheckPlanContext} context - Validated candidate context.
17
+ * @returns {import("../semantic/types.js").TargetCheckPlan} Immutable Kotlin plan.
18
+ */
19
+ export function createKotlinCheckPlan(context) {
20
+ const tool = checkTool(context, "kotlinc", "kotlin")
21
+ const artifacts = checkArtifacts(context, artifact => artifact.path.endsWith(".kt"), "kotlin", "only staged '.kt' artifacts")
22
+ const classes = path.join(context.buildPath, "classes")
23
+ const home = path.join(context.buildPath, "home")
24
+ const cache = path.join(context.buildPath, "cache")
25
+ const temporary = path.join(context.buildPath, "tmp")
26
+
27
+ return checkPlan(context, "kotlin", artifacts, [checkStage({
28
+ argv: ["-language-version", "2.4", "-api-version", "2.4", "-jvm-target", "25", "-Werror", ...artifacts, "-d", classes],
29
+ cwd: context.sourcePath,
30
+ environment: {HOME: home, TMPDIR: temporary, XDG_CACHE_HOME: cache},
31
+ environmentPaths: [environmentPath("HOME", "build"), environmentPath("TMPDIR", "build"), environmentPath("XDG_CACHE_HOME", "build")],
32
+ inputs: artifacts,
33
+ output: checkOutput(context.buildPath, "application/java-vm", "compiler-output"),
34
+ pathArguments: [
35
+ ...artifacts.map((_, index) => pathArgument(7 + index, "source")),
36
+ pathArgument(8 + artifacts.length, "build")
37
+ ],
38
+ stage: "compile",
39
+ tool
40
+ })])
41
+ }
@@ -15,7 +15,7 @@ export const kotlinArtifactMetadata = Object.freeze({
15
15
  toolchain: "kotlinc",
16
16
  version: "2.4.20"
17
17
  }),
18
- run: Object.freeze({arguments: Object.freeze(["-jar", "Program.jar"]), toolchain: "java25", version: "25.0.4+7"})
18
+ run: Object.freeze({arguments: Object.freeze(["-jar", "Program.jar"]), toolchain: "java25", version: "25.0.4.1"})
19
19
  })
20
20
 
21
21
  /**
@@ -0,0 +1,23 @@
1
+ // @ts-check
2
+
3
+ import {checkArtifacts, checkPlan, checkStage, checkTool, pathArgument} from "./check-plan.js"
4
+
5
+ /**
6
+ * Constructs PHP's non-executing syntax-check plan.
7
+ * @param {import("../language-registry.js").TargetCheckPlanContext} context - Validated candidate context.
8
+ * @returns {import("../semantic/types.js").TargetCheckPlan} Immutable PHP plan.
9
+ */
10
+ export function createPhpCheckPlan(context) {
11
+ const tool = checkTool(context, "php82", "php")
12
+ const artifacts = checkArtifacts(context, artifact => artifact.path.endsWith(".php"), "php", "only staged '.php' artifacts")
13
+
14
+ return checkPlan(context, "php", artifacts, artifacts.map(artifact => checkStage({
15
+ argv: ["-n", "-l", artifact],
16
+ cwd: context.sourcePath,
17
+ inputs: [artifact],
18
+ output: null,
19
+ pathArguments: [pathArgument(2, "source")],
20
+ stage: "validate",
21
+ tool
22
+ })))
23
+ }
@@ -25,6 +25,23 @@ const programTargets = new Set(["php", "ruby", "javascript", "typescript", "java
25
25
  /** @type {Readonly<Set<import("../semantic/types.js").BackendLanguage>>} */
26
26
  const programApplicationTargets = new Set(["android", "ios", "flutter"])
27
27
 
28
+ /**
29
+ * Reports whether program generation implements one registered target/role combination.
30
+ * @param {string} language - Registered target identity.
31
+ * @param {string} role - Explicit project target role.
32
+ * @returns {boolean} Whether complete semantic programs support the combination.
33
+ */
34
+ export function supportsProgramArtifactRole(language, role) {
35
+ if (role == "text") {
36
+ return programTargets.has(/** @type {import("../semantic/types.js").SemanticLanguage} */ (language))
37
+ }
38
+ if (role == "application") {
39
+ return programApplicationTargets.has(/** @type {import("../semantic/types.js").BackendLanguage} */ (language))
40
+ }
41
+
42
+ return false
43
+ }
44
+
28
45
  /**
29
46
  * Validates and prepares a complete semantic program for a non-text backend without allocating a writer.
30
47
  * @param {object} input - Backend preflight request.