semantifold 0.9.0 → 0.10.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.
- package/README.md +6 -3
- package/bin/semantifold.js +6 -0
- package/build/bin/semantifold.d.ts +3 -0
- package/build/bin/semantifold.d.ts.map +1 -0
- package/build/bin/semantifold.js +5 -0
- package/build/index.d.ts +8 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +9 -1
- package/build/src/artifact-path.d.ts +16 -0
- package/build/src/artifact-path.d.ts.map +1 -1
- package/build/src/artifact-path.js +29 -3
- package/build/src/backends/c-check.d.ts +7 -0
- package/build/src/backends/c-check.d.ts.map +1 -0
- package/build/src/backends/c-check.js +65 -0
- package/build/src/backends/check-plan.d.ts +96 -0
- package/build/src/backends/check-plan.d.ts.map +1 -0
- package/build/src/backends/check-plan.js +135 -0
- package/build/src/backends/cpp-check.d.ts +7 -0
- package/build/src/backends/cpp-check.d.ts.map +1 -0
- package/build/src/backends/cpp-check.js +59 -0
- package/build/src/backends/csharp-check.d.ts +7 -0
- package/build/src/backends/csharp-check.d.ts.map +1 -0
- package/build/src/backends/csharp-check.js +125 -0
- package/build/src/backends/csharp.d.ts +1 -0
- package/build/src/backends/csharp.d.ts.map +1 -1
- package/build/src/backends/csharp.js +5 -4
- package/build/src/backends/dart-check.d.ts +7 -0
- package/build/src/backends/dart-check.d.ts.map +1 -0
- package/build/src/backends/dart-check.js +103 -0
- package/build/src/backends/dart.d.ts +2 -0
- package/build/src/backends/dart.d.ts.map +1 -1
- package/build/src/backends/dart.js +5 -5
- package/build/src/backends/go-check.d.ts +7 -0
- package/build/src/backends/go-check.d.ts.map +1 -0
- package/build/src/backends/go-check.js +77 -0
- package/build/src/backends/go.d.ts +1 -0
- package/build/src/backends/go.d.ts.map +1 -1
- package/build/src/backends/go.js +3 -3
- package/build/src/backends/java-check.d.ts +21 -0
- package/build/src/backends/java-check.d.ts.map +1 -0
- package/build/src/backends/java-check.js +73 -0
- package/build/src/backends/javascript-check.d.ts +7 -0
- package/build/src/backends/javascript-check.d.ts.map +1 -0
- package/build/src/backends/javascript-check.js +29 -0
- package/build/src/backends/kotlin-check.d.ts +7 -0
- package/build/src/backends/kotlin-check.d.ts.map +1 -0
- package/build/src/backends/kotlin-check.js +31 -0
- package/build/src/backends/php-check.d.ts +7 -0
- package/build/src/backends/php-check.d.ts.map +1 -0
- package/build/src/backends/php-check.js +21 -0
- package/build/src/backends/program.d.ts +7 -0
- package/build/src/backends/program.d.ts.map +1 -1
- package/build/src/backends/program.js +16 -1
- package/build/src/backends/python-check.d.ts +7 -0
- package/build/src/backends/python-check.d.ts.map +1 -0
- package/build/src/backends/python-check.js +28 -0
- package/build/src/backends/ruby-check.d.ts +7 -0
- package/build/src/backends/ruby-check.d.ts.map +1 -0
- package/build/src/backends/ruby-check.js +21 -0
- package/build/src/backends/rust-check.d.ts +7 -0
- package/build/src/backends/rust-check.d.ts.map +1 -0
- package/build/src/backends/rust-check.js +65 -0
- package/build/src/backends/swift-check.d.ts +7 -0
- package/build/src/backends/swift-check.d.ts.map +1 -0
- package/build/src/backends/swift-check.js +77 -0
- package/build/src/backends/typescript-check.d.ts +7 -0
- package/build/src/backends/typescript-check.d.ts.map +1 -0
- package/build/src/backends/typescript-check.js +33 -0
- package/build/src/backends/zig-check.d.ts +7 -0
- package/build/src/backends/zig-check.d.ts.map +1 -0
- package/build/src/backends/zig-check.js +70 -0
- package/build/src/diagnostic.d.ts +13 -1
- package/build/src/diagnostic.d.ts.map +1 -1
- package/build/src/diagnostic.js +14 -2
- package/build/src/frontends/program.d.ts +6 -0
- package/build/src/frontends/program.d.ts.map +1 -1
- package/build/src/frontends/program.js +9 -1
- package/build/src/language-registry.d.ts +54 -0
- package/build/src/language-registry.d.ts.map +1 -1
- package/build/src/language-registry.js +107 -5
- package/build/src/project-build.d.ts +172 -0
- package/build/src/project-build.d.ts.map +1 -0
- package/build/src/project-build.js +320 -0
- package/build/src/project-cli.d.ts +40 -0
- package/build/src/project-cli.d.ts.map +1 -0
- package/build/src/project-cli.js +145 -0
- package/build/src/project-manifest.d.ts +148 -0
- package/build/src/project-manifest.d.ts.map +1 -0
- package/build/src/project-manifest.js +432 -0
- package/build/src/project-reporter.d.ts +81 -0
- package/build/src/project-reporter.d.ts.map +1 -0
- package/build/src/project-reporter.js +293 -0
- package/build/src/project-snapshot.d.ts +129 -0
- package/build/src/project-snapshot.d.ts.map +1 -0
- package/build/src/project-snapshot.js +362 -0
- package/build/src/project-watch-reporter.d.ts +125 -0
- package/build/src/project-watch-reporter.d.ts.map +1 -0
- package/build/src/project-watch-reporter.js +280 -0
- package/build/src/project-watch.d.ts +133 -0
- package/build/src/project-watch.d.ts.map +1 -0
- package/build/src/project-watch.js +839 -0
- package/build/src/publication.d.ts +69 -5
- package/build/src/publication.d.ts.map +1 -1
- package/build/src/publication.js +246 -57
- package/build/src/semantic/types.d.ts +303 -2
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +79 -2
- package/build/src/subprocess.d.ts +8 -0
- package/build/src/subprocess.d.ts.map +1 -1
- package/build/src/subprocess.js +50 -9
- package/build/src/target-check.d.ts +52 -0
- package/build/src/target-check.d.ts.map +1 -0
- package/build/src/target-check.js +796 -0
- package/build/src/toolchains.d.ts.map +1 -1
- package/build/src/toolchains.js +3 -3
- package/docs/architecture.md +3 -1
- package/docs/c.md +4 -0
- package/docs/cpp.md +4 -0
- package/docs/dart.md +4 -0
- package/docs/generated-artifact-publication.md +11 -8
- package/docs/kotlin.md +2 -2
- package/docs/language-support.md +29 -3
- package/docs/project-build-cli.md +147 -0
- package/docs/project-watch.md +60 -0
- package/docs/rust.md +4 -0
- package/docs/swift.md +2 -0
- package/docs/testing.md +70 -3
- package/docs/watch-build-pipeline.md +39 -23
- package/docs/zig.md +2 -0
- package/examples/jsdoc-java-watch/expected-output.txt +3 -0
- package/examples/jsdoc-java-watch/semantifold.json +23 -0
- package/examples/jsdoc-java-watch/src/main.js +21 -0
- package/index.js +8 -0
- package/package.json +6 -1
- package/src/artifact-path.js +31 -2
- package/src/backends/c-check.js +80 -0
- package/src/backends/check-plan.js +147 -0
- package/src/backends/cpp-check.js +73 -0
- package/src/backends/csharp-check.js +139 -0
- package/src/backends/csharp.js +4 -3
- package/src/backends/dart-check.js +117 -0
- package/src/backends/dart.js +4 -4
- package/src/backends/go-check.js +89 -0
- package/src/backends/go.js +2 -2
- package/src/backends/java-check.js +77 -0
- package/src/backends/javascript-check.js +33 -0
- package/src/backends/kotlin-check.js +41 -0
- package/src/backends/php-check.js +23 -0
- package/src/backends/program.js +17 -0
- package/src/backends/python-check.js +30 -0
- package/src/backends/ruby-check.js +23 -0
- package/src/backends/rust-check.js +78 -0
- package/src/backends/swift-check.js +89 -0
- package/src/backends/typescript-check.js +37 -0
- package/src/backends/zig-check.js +81 -0
- package/src/diagnostic.js +9 -1
- package/src/frontends/program.js +9 -0
- package/src/language-registry.js +113 -4
- package/src/project-build.js +353 -0
- package/src/project-cli.js +155 -0
- package/src/project-manifest.js +479 -0
- package/src/project-reporter.js +320 -0
- package/src/project-snapshot.js +403 -0
- package/src/project-watch-reporter.js +303 -0
- package/src/project-watch.js +870 -0
- package/src/publication.js +275 -58
- package/src/semantic/types.js +87 -1
- package/src/subprocess.js +49 -8
- package/src/target-check.js +844 -0
- package/src/toolchains.js +3 -2
- package/tsconfig.json +1 -1
package/src/backends/dart.js
CHANGED
|
@@ -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
|
|
11
|
-
const
|
|
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:
|
|
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:
|
|
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
|
+
}
|
package/src/backends/go.js
CHANGED
|
@@ -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
|
|
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:
|
|
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
|
+
}
|
|
@@ -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
|
+
}
|
package/src/backends/program.js
CHANGED
|
@@ -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.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import path from "node:path"
|
|
4
|
+
import {checkArtifacts, checkOutput, checkPlan, checkStage, checkTool, pathArgument} from "./check-plan.js"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Constructs Python's isolated bytecode compiler plan.
|
|
8
|
+
* @param {import("../language-registry.js").TargetCheckPlanContext} context - Validated candidate context.
|
|
9
|
+
* @returns {import("../semantic/types.js").TargetCheckPlan} Immutable Python plan.
|
|
10
|
+
*/
|
|
11
|
+
export function createPythonCheckPlan(context) {
|
|
12
|
+
const tool = checkTool(context, "python", "python")
|
|
13
|
+
const artifacts = checkArtifacts(context, artifact => artifact.path.endsWith(".py"), "python", "only staged '.py' artifacts")
|
|
14
|
+
const compiler = "import py_compile,sys;[py_compile.compile(sys.argv[index],cfile=sys.argv[index+1],dfile=sys.argv[index+2],doraise=True,invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH) for index in range(1,len(sys.argv),3)]"
|
|
15
|
+
const arguments_ = artifacts.flatMap(artifactPath => [
|
|
16
|
+
artifactPath,
|
|
17
|
+
path.join(context.buildPath, `${path.basename(artifactPath, ".py")}.pyc`),
|
|
18
|
+
path.basename(artifactPath)
|
|
19
|
+
])
|
|
20
|
+
|
|
21
|
+
return checkPlan(context, "python", artifacts, [checkStage({
|
|
22
|
+
argv: ["-I", "-B", "-c", compiler, ...arguments_],
|
|
23
|
+
cwd: context.sourcePath,
|
|
24
|
+
inputs: artifacts,
|
|
25
|
+
output: checkOutput(context.buildPath, "application/x-python-bytecode", "compiler-output"),
|
|
26
|
+
pathArguments: artifacts.flatMap((_, index) => [pathArgument(4 + index * 3, "source"), pathArgument(5 + index * 3, "build")]),
|
|
27
|
+
stage: "compile",
|
|
28
|
+
tool
|
|
29
|
+
})])
|
|
30
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import {checkArtifacts, checkPlan, checkStage, checkTool, pathArgument} from "./check-plan.js"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Constructs Ruby'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 Ruby plan.
|
|
9
|
+
*/
|
|
10
|
+
export function createRubyCheckPlan(context) {
|
|
11
|
+
const tool = checkTool(context, "ruby", "ruby")
|
|
12
|
+
const artifacts = checkArtifacts(context, artifact => artifact.path.endsWith(".rb"), "ruby", "only staged '.rb' artifacts")
|
|
13
|
+
|
|
14
|
+
return checkPlan(context, "ruby", artifacts, artifacts.map(artifact => checkStage({
|
|
15
|
+
argv: ["--disable=gems", "-c", artifact],
|
|
16
|
+
cwd: context.sourcePath,
|
|
17
|
+
inputs: [artifact],
|
|
18
|
+
output: null,
|
|
19
|
+
pathArguments: [pathArgument(2, "source")],
|
|
20
|
+
stage: "validate",
|
|
21
|
+
tool
|
|
22
|
+
})))
|
|
23
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import path from "node:path"
|
|
4
|
+
import {SemantifoldDiagnostic} from "../diagnostic.js"
|
|
5
|
+
import {
|
|
6
|
+
checkArtifacts,
|
|
7
|
+
checkPlan,
|
|
8
|
+
checkStage,
|
|
9
|
+
checkTool,
|
|
10
|
+
environmentPath,
|
|
11
|
+
environmentTool,
|
|
12
|
+
pathArgument
|
|
13
|
+
} from "./check-plan.js"
|
|
14
|
+
import {rustLockfile, rustManifest} from "./rust-runtime.js"
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Constructs Rust's locked offline Cargo build/check plan.
|
|
18
|
+
* @param {import("../language-registry.js").TargetCheckPlanContext} context - Validated candidate context.
|
|
19
|
+
* @returns {import("../semantic/types.js").TargetCheckPlan} Immutable Cargo plan.
|
|
20
|
+
*/
|
|
21
|
+
export function createRustCheckPlan(context) {
|
|
22
|
+
const rustc = checkTool(context, "rustc", "rust")
|
|
23
|
+
const cargo = checkTool(context, "cargo", "rust")
|
|
24
|
+
const artifacts = checkArtifacts(context, artifact => artifact.path.endsWith(".rs") ||
|
|
25
|
+
artifact.path == "Cargo.toml" || artifact.path == "Cargo.lock",
|
|
26
|
+
"rust", "only staged Rust source and canonical Cargo manifest/lock artifacts")
|
|
27
|
+
const manifest = context.artifacts.artifacts.filter(artifact => artifact.path == "Cargo.toml")
|
|
28
|
+
const lock = context.artifacts.artifacts.filter(artifact => artifact.path == "Cargo.lock")
|
|
29
|
+
const sources = artifacts.filter(artifact => artifact.endsWith(".rs"))
|
|
30
|
+
|
|
31
|
+
if (manifest.length != 1 || manifest[0].contentKind != "text" || manifest[0].role != "manifest" ||
|
|
32
|
+
manifest[0].content != rustManifest || lock.length != 1 || lock[0].contentKind != "text" ||
|
|
33
|
+
lock[0].content != rustLockfile || artifacts.length != 3 || sources.length != 1 ||
|
|
34
|
+
sources[0] != path.join(context.sourcePath, "src/main.rs")) {
|
|
35
|
+
throw new SemantifoldDiagnostic({
|
|
36
|
+
code: "INVALID_TARGET_CHECK_PLAN",
|
|
37
|
+
language: "rust",
|
|
38
|
+
message: "Rust developer checks require the exact dependency-free Cargo project/lock and staged '.rs' source."
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
const cargoHome = path.join(context.buildPath, "cargo-home")
|
|
42
|
+
const home = path.join(context.buildPath, "home")
|
|
43
|
+
const temporary = path.join(context.buildPath, "tmp")
|
|
44
|
+
const target = path.join(context.buildPath, "cargo-target")
|
|
45
|
+
const environment = {
|
|
46
|
+
CARGO_HOME: cargoHome,
|
|
47
|
+
CARGO_INCREMENTAL: "0",
|
|
48
|
+
CARGO_NET_OFFLINE: "true",
|
|
49
|
+
CARGO_TERM_COLOR: "never",
|
|
50
|
+
HOME: home,
|
|
51
|
+
PATH: [path.dirname(rustc.executable), path.dirname(cargo.executable), "/usr/local/bin", "/usr/bin", "/bin"].filter((value, index, values) =>
|
|
52
|
+
values.indexOf(value) == index).join(path.delimiter),
|
|
53
|
+
RUSTC: rustc.executable,
|
|
54
|
+
TMPDIR: temporary
|
|
55
|
+
}
|
|
56
|
+
const environmentPaths = [environmentPath("CARGO_HOME", "build"), environmentPath("HOME", "build"),
|
|
57
|
+
environmentTool("RUSTC", rustc), environmentPath("TMPDIR", "build")]
|
|
58
|
+
/**
|
|
59
|
+
* Constructs one Cargo stage over the complete generated project.
|
|
60
|
+
* @param {import("../semantic/types.js").AcceptanceStage} name - Registry stage identity.
|
|
61
|
+
* @param {string} command - Exact Cargo subcommand.
|
|
62
|
+
* @returns {import("../semantic/types.js").TargetCheckStageRequest} Immutable stage.
|
|
63
|
+
*/
|
|
64
|
+
const stage = (name, command) => checkStage({
|
|
65
|
+
argv: [command, "--offline", "--locked", "--target-dir", target],
|
|
66
|
+
cwd: context.sourcePath,
|
|
67
|
+
environment,
|
|
68
|
+
environmentPaths,
|
|
69
|
+
inputs: artifacts,
|
|
70
|
+
output: null,
|
|
71
|
+
pathArguments: [pathArgument(4, "build")],
|
|
72
|
+
stage: name,
|
|
73
|
+
tool: cargo,
|
|
74
|
+
transientPaths: [target]
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
return checkPlan(context, "rust", artifacts, [stage("compile", "build"), stage("validate", "check")])
|
|
78
|
+
}
|
|
@@ -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
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Constructs Swift's warnings-as-errors type-check/compile plan.
|
|
17
|
+
* @param {import("../language-registry.js").TargetCheckPlanContext} context - Validated candidate context.
|
|
18
|
+
* @returns {import("../semantic/types.js").TargetCheckPlan} Immutable Swift plan.
|
|
19
|
+
*/
|
|
20
|
+
export function createSwiftCheckPlan(context) {
|
|
21
|
+
const tool = checkTool(context, "swiftc", "swift")
|
|
22
|
+
const artifacts = checkArtifacts(context, artifact => artifact.path.endsWith(".swift"), "swift", "only staged '.swift' sources")
|
|
23
|
+
|
|
24
|
+
if (artifacts.length != 1 || artifacts[0] != path.join(context.sourcePath, "program.swift")) {
|
|
25
|
+
throw new SemantifoldDiagnostic({code: "INVALID_TARGET_CHECK_PLAN", language: "swift",
|
|
26
|
+
message: "Swift developer checks require the exact producer-owned 'program.swift' source."})
|
|
27
|
+
}
|
|
28
|
+
const home = path.join(context.buildPath, "home")
|
|
29
|
+
const cache = path.join(context.buildPath, "cache")
|
|
30
|
+
const temporary = path.join(context.buildPath, "tmp")
|
|
31
|
+
const environment = {
|
|
32
|
+
HOME: home,
|
|
33
|
+
PATH: [path.dirname(tool.executable), "/usr/bin", "/usr/local/bin", "/bin"].filter((value, index, values) =>
|
|
34
|
+
values.indexOf(value) == index).join(path.delimiter),
|
|
35
|
+
TMPDIR: temporary,
|
|
36
|
+
XDG_CACHE_HOME: cache
|
|
37
|
+
}
|
|
38
|
+
const environmentPaths = [environmentPath("HOME", "build"), environmentPath("TMPDIR", "build"),
|
|
39
|
+
environmentPath("XDG_CACHE_HOME", "build")]
|
|
40
|
+
const objects = path.join(context.buildPath, "objects")
|
|
41
|
+
const object = path.join(objects, "program.o")
|
|
42
|
+
const binary = path.join(context.buildPath, "semantifold-swift")
|
|
43
|
+
const typecheckArgv = [
|
|
44
|
+
"--driver-mode=swiftc", "-warnings-as-errors", "-typecheck", "-module-name", "SemantifoldGenerated", ...artifacts
|
|
45
|
+
]
|
|
46
|
+
const compileArgv = [
|
|
47
|
+
"--driver-mode=swiftc", "-warnings-as-errors", "-c", ...artifacts,
|
|
48
|
+
"-module-name", "SemantifoldGenerated", "-o", "program.o"
|
|
49
|
+
]
|
|
50
|
+
const linkArgv = ["--driver-mode=swiftc", object, "-Xlinker", "--build-id=none", "-o", binary]
|
|
51
|
+
|
|
52
|
+
return checkPlan(context, "swift", artifacts, [
|
|
53
|
+
checkStage({
|
|
54
|
+
argv: typecheckArgv,
|
|
55
|
+
cwd: context.sourcePath,
|
|
56
|
+
environment,
|
|
57
|
+
environmentPaths,
|
|
58
|
+
inputs: artifacts,
|
|
59
|
+
output: null,
|
|
60
|
+
pathArguments: artifacts.map((_, index) => pathArgument(index + 5, "source")),
|
|
61
|
+
stage: "compile",
|
|
62
|
+
tool
|
|
63
|
+
}),
|
|
64
|
+
checkStage({
|
|
65
|
+
argv: compileArgv,
|
|
66
|
+
cwd: objects,
|
|
67
|
+
environment,
|
|
68
|
+
environmentPaths,
|
|
69
|
+
inputs: artifacts,
|
|
70
|
+
output: null,
|
|
71
|
+
pathArguments: artifacts.map((_, index) => pathArgument(index + 3, "source")),
|
|
72
|
+
stage: "compile",
|
|
73
|
+
tool,
|
|
74
|
+
transientPaths: [objects]
|
|
75
|
+
}),
|
|
76
|
+
checkStage({
|
|
77
|
+
argv: linkArgv,
|
|
78
|
+
cwd: context.buildPath,
|
|
79
|
+
environment,
|
|
80
|
+
environmentPaths,
|
|
81
|
+
inputs: [object],
|
|
82
|
+
output: checkOutput(context.buildPath, "application/x-executable", "compiler-output"),
|
|
83
|
+
pathArguments: [pathArgument(1, "build"), pathArgument(linkArgv.length - 1, "build")],
|
|
84
|
+
stage: "compile",
|
|
85
|
+
tool,
|
|
86
|
+
transientPaths: [objects]
|
|
87
|
+
})
|
|
88
|
+
])
|
|
89
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import path from "node:path"
|
|
4
|
+
import {SemantifoldDiagnostic} from "../diagnostic.js"
|
|
5
|
+
import {checkArtifacts, checkPlan, checkStage, checkTool, pathArgument} from "./check-plan.js"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Constructs TypeScript's non-emitting compiler plan.
|
|
9
|
+
* @param {import("../language-registry.js").TargetCheckPlanContext} context - Validated candidate context.
|
|
10
|
+
* @returns {import("../semantic/types.js").TargetCheckPlan} Immutable TypeScript plan.
|
|
11
|
+
*/
|
|
12
|
+
export function createTypeScriptCheckPlan(context) {
|
|
13
|
+
const tool = checkTool(context, "tsc", "typescript")
|
|
14
|
+
const artifacts = checkArtifacts(context, artifact => artifact.path.endsWith(".ts") || path.basename(artifact.path) == "package.json",
|
|
15
|
+
"typescript", "only staged '.ts' artifacts and package manifests")
|
|
16
|
+
const sources = artifacts.filter(artifact => artifact.endsWith(".ts"))
|
|
17
|
+
|
|
18
|
+
if (sources.length == 0) {
|
|
19
|
+
throw new SemantifoldDiagnostic({code: "INVALID_TARGET_CHECK_PLAN", language: "typescript",
|
|
20
|
+
message: "TypeScript developer checks require at least one staged '.ts' artifact."})
|
|
21
|
+
}
|
|
22
|
+
const typeRoots = path.join(context.buildPath, "types")
|
|
23
|
+
const argv = [
|
|
24
|
+
"--pretty", "false", "--noEmit", "--incremental", "false", "--target", "ES2024", "--module", "NodeNext",
|
|
25
|
+
"--moduleResolution", "NodeNext", "--typeRoots", typeRoots, ...sources
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
return checkPlan(context, "typescript", artifacts, [checkStage({
|
|
29
|
+
argv,
|
|
30
|
+
cwd: context.sourcePath,
|
|
31
|
+
inputs: artifacts,
|
|
32
|
+
output: null,
|
|
33
|
+
pathArguments: [pathArgument(12, "build"), ...sources.map((_, index) => pathArgument(13 + index, "source"))],
|
|
34
|
+
stage: "compile",
|
|
35
|
+
tool
|
|
36
|
+
})])
|
|
37
|
+
}
|