lawspec 0.8.0 → 0.9.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/API-MIGRATION.md +102 -1
- package/GO.md +144 -0
- package/HASKELL.md +171 -0
- package/JAVA.md +113 -0
- package/KOTLIN.md +214 -0
- package/LANGUAGE.md +237 -12
- package/PRIMITIVES.md +1 -1
- package/PYTHON.md +152 -0
- package/README.md +26 -13
- package/REFINEMENTS.md +289 -3
- package/RELEASE-0.9.md +61 -0
- package/RUST.md +115 -1
- package/WEB.md +144 -0
- package/api.mjs +8 -2
- package/bin/lawspec.mjs +9 -6
- package/build.json +179 -37
- package/core.wasm +0 -0
- package/examples/specs/collections.lawspec +67 -0
- package/examples/specs/data_types.lawspec +66 -0
- package/examples/specs/finite_data.lawspec +37 -0
- package/examples/specs/list_contracts.lawspec +136 -0
- package/examples/specs/list_refinements.lawspec +51 -0
- package/examples/specs/matching.lawspec +49 -0
- package/examples/specs/recursive_refinements.lawspec +41 -0
- package/examples/specs/refined_definitions.lawspec +44 -0
- package/examples/specs/sum_refinements.lawspec +49 -0
- package/examples/specs/total_functions.lawspec +101 -0
- package/examples-command.mjs +6 -1
- package/files.mjs +10 -1
- package/index.d.ts +246 -27
- package/package.json +2 -2
- package/templates.mjs +107 -17
package/index.d.ts
CHANGED
|
@@ -1,29 +1,248 @@
|
|
|
1
1
|
// Generated from LawSpec.Gen. Do not edit.
|
|
2
|
-
export type Target =
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export interface
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export interface
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
export interface
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
export interface
|
|
2
|
+
export type Target =
|
|
3
|
+
'java' |
|
|
4
|
+
'python' |
|
|
5
|
+
'javascript' |
|
|
6
|
+
'typescript' |
|
|
7
|
+
'go' |
|
|
8
|
+
'haskell' |
|
|
9
|
+
'kotlin' |
|
|
10
|
+
'rust';
|
|
11
|
+
|
|
12
|
+
export interface Source {
|
|
13
|
+
path: string;
|
|
14
|
+
content: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface Location {
|
|
18
|
+
file: string;
|
|
19
|
+
line: number;
|
|
20
|
+
column: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface Span {
|
|
24
|
+
start: Location;
|
|
25
|
+
end: Location;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface Diagnostic {
|
|
29
|
+
code: string;
|
|
30
|
+
message: string;
|
|
31
|
+
at: Location | null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface Artifact {
|
|
35
|
+
path: string;
|
|
36
|
+
content: string;
|
|
37
|
+
ownership: 'user' | 'generated';
|
|
38
|
+
placement: 'source' | 'test';
|
|
39
|
+
adapterReference?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type Type =
|
|
43
|
+
{kind: 'constructor'; name: string; arguments: TypeArgument[];} |
|
|
44
|
+
{kind: 'variable'; id: string;} |
|
|
45
|
+
{kind: 'function'; parameter: Type; result: Type;};
|
|
46
|
+
|
|
47
|
+
export type TypeArgument =
|
|
48
|
+
{kind: 'type'; type: Type;} |
|
|
49
|
+
{kind: 'natural'; value: string;} |
|
|
50
|
+
{kind: 'indexVariable'; id: string;};
|
|
51
|
+
|
|
52
|
+
export type Origin =
|
|
53
|
+
{kind: 'source'; span: Span;} | {kind: 'generated'; declaration: string;};
|
|
54
|
+
|
|
55
|
+
export type Evidence = {kind: 'numeric' | 'structural'; type: Type;};
|
|
56
|
+
|
|
57
|
+
export interface Expr {
|
|
58
|
+
type: Type;
|
|
59
|
+
origin: Origin;
|
|
60
|
+
text: string;
|
|
61
|
+
node: ExprNode;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export type ExprNode =
|
|
65
|
+
{kind: 'constant'; value: ScalarValue;} |
|
|
66
|
+
{kind: 'match'; value: Expr; cases: MatchCase[];} |
|
|
67
|
+
{kind: 'allElements'; value: Expr; binder: Binder; predicate: Expr;} |
|
|
68
|
+
{kind: 'allPayloads'; value: Expr; predicates: PayloadPredicate[];} |
|
|
69
|
+
{kind: 'construct'; constructor: string; arguments: Expr[];} |
|
|
70
|
+
{kind: 'local'; id: string;} |
|
|
71
|
+
{kind: 'call'; declaration: string; arguments: Expr[];} |
|
|
72
|
+
{
|
|
73
|
+
kind: 'binary';
|
|
74
|
+
operator: string;
|
|
75
|
+
evidence: Evidence;
|
|
76
|
+
left: Expr;
|
|
77
|
+
right: Expr;
|
|
78
|
+
} |
|
|
79
|
+
{kind: 'unary'; operator: '-' | '!'; argument: Expr;} |
|
|
80
|
+
{kind: 'shortCircuit'; operator: '&&' | '||'; left: Expr; right: Expr;} |
|
|
81
|
+
{kind: 'convert'; conversion: 'explicit' | 'checked'; argument: Expr;} |
|
|
82
|
+
{kind: 'helper'; name: string; arguments: Expr[];};
|
|
83
|
+
|
|
84
|
+
export type Assertion =
|
|
85
|
+
{kind: 'equal'; evidence: Evidence; left: Expr; right: Expr;} |
|
|
86
|
+
{kind: 'implies'; guard: Expr; body: Assertion;} |
|
|
87
|
+
{kind: 'all'; items: Assertion[];};
|
|
88
|
+
|
|
89
|
+
export interface Generation {
|
|
90
|
+
cases: number;
|
|
91
|
+
maxAttempts: number;
|
|
92
|
+
maxShrinks: number;
|
|
93
|
+
exhaustiveLimit: number;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface Binder {
|
|
97
|
+
id: string;
|
|
98
|
+
name: string;
|
|
99
|
+
type: Type;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface Definition {
|
|
103
|
+
owner: string;
|
|
104
|
+
id: string;
|
|
105
|
+
arguments: Binder[];
|
|
106
|
+
body: Expr;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface Input extends Binder {
|
|
110
|
+
predicates: Expr[];
|
|
111
|
+
bounds: {operator: string; value: Expr;}[];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface Example {
|
|
115
|
+
name: string;
|
|
116
|
+
bindings: (Binder & {value: DataValue;})[];
|
|
117
|
+
expectations: Assertion[];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface Law {
|
|
121
|
+
id: string;
|
|
122
|
+
owner: string;
|
|
123
|
+
name: string;
|
|
124
|
+
inputs: Input[];
|
|
125
|
+
assertion: Assertion;
|
|
126
|
+
examples: Example[];
|
|
127
|
+
description: string;
|
|
128
|
+
rationale: string;
|
|
129
|
+
references: string[];
|
|
130
|
+
location: Location;
|
|
131
|
+
trace: string[];
|
|
132
|
+
generation: Generation;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export interface Unit {
|
|
136
|
+
id: string;
|
|
137
|
+
declarations: (Binder & {origin: Origin;})[];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface DataTypeDeclaration {
|
|
141
|
+
id: string;
|
|
142
|
+
name: string;
|
|
143
|
+
parameters: string[];
|
|
144
|
+
origin: Origin;
|
|
145
|
+
constructors: {id: string; name: string; fields: Binder[]; origin: Origin;}[];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface Contract {
|
|
149
|
+
id: string;
|
|
150
|
+
name: string;
|
|
151
|
+
arguments: Binder[];
|
|
152
|
+
result: Binder;
|
|
153
|
+
preconditions: Expr[];
|
|
154
|
+
postconditions: Expr[];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface Refinement {
|
|
158
|
+
owner: string;
|
|
159
|
+
name: string;
|
|
160
|
+
parameters: {name: string; kind: 'type' | 'value'; type: string;}[];
|
|
161
|
+
requirements: {capability: string; type: string;}[];
|
|
162
|
+
definition: string;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface CheckRequest {
|
|
166
|
+
sources: Source[];
|
|
167
|
+
schemaVersion?: 3;
|
|
168
|
+
machineBits?: 32 | 64;
|
|
169
|
+
generation?: Partial<Generation>;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export interface GenerationRequest extends CheckRequest {
|
|
173
|
+
target: Target;
|
|
174
|
+
sourceDir?: string;
|
|
175
|
+
testDir?: string;
|
|
176
|
+
minify?: boolean;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface Result {
|
|
180
|
+
schemaVersion: 3;
|
|
181
|
+
machineBits?: 32 | 64;
|
|
182
|
+
generation?: Generation;
|
|
183
|
+
units?: Unit[];
|
|
184
|
+
dataTypes?: DataTypeDeclaration[];
|
|
185
|
+
definitions?: Definition[];
|
|
186
|
+
laws?: Law[];
|
|
187
|
+
contracts?: {owner: string; contract: Contract;}[];
|
|
188
|
+
refinements?: Refinement[];
|
|
189
|
+
diagnostics: Diagnostic[];
|
|
190
|
+
expansions?: string[];
|
|
191
|
+
files?: Artifact[];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface PayloadPredicate {
|
|
195
|
+
binder: Binder;
|
|
196
|
+
predicate: Expr;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export interface MatchCase {
|
|
200
|
+
constructor: string;
|
|
201
|
+
binders: Binder[];
|
|
202
|
+
body: Expr;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export type DataValue =
|
|
206
|
+
ScalarValue |
|
|
207
|
+
{kind: 'data'; type: Type; constructor: string; fields: DataValue[];};
|
|
208
|
+
|
|
209
|
+
export type IntegerType =
|
|
210
|
+
'Int8' |
|
|
211
|
+
'Int16' |
|
|
212
|
+
'Int32' |
|
|
213
|
+
'Int64' |
|
|
214
|
+
'UInt8' |
|
|
215
|
+
'UInt16' |
|
|
216
|
+
'UInt32' |
|
|
217
|
+
'UInt64' |
|
|
218
|
+
'IntSize' |
|
|
219
|
+
'UIntSize' |
|
|
220
|
+
'UIntPtr' |
|
|
221
|
+
'Integer' |
|
|
222
|
+
'BigInt' |
|
|
223
|
+
'BigUInt';
|
|
224
|
+
|
|
225
|
+
export type ScalarValue =
|
|
226
|
+
{type: IntegerType; value: string;} |
|
|
227
|
+
{type: 'Bool'; value: boolean;} |
|
|
228
|
+
{type: 'Decimal'; coefficient: string; exponent: string;} |
|
|
229
|
+
{type: 'Rational'; numerator: string; denominator: string;} |
|
|
230
|
+
{type: 'Float32' | 'Float64'; bits: string;} |
|
|
231
|
+
{
|
|
232
|
+
type: 'Complex64' | 'Complex128';
|
|
233
|
+
real: ScalarValue;
|
|
234
|
+
imaginary: ScalarValue;
|
|
235
|
+
} |
|
|
236
|
+
{type: 'Char' | 'CodePoint' | 'CodeUnit16'; value: number;} |
|
|
237
|
+
{type: 'Text' | 'CodePointText' | 'Utf16Text' | 'Bytes'; units: number[];} |
|
|
238
|
+
{type: 'Symbol'; id: string; description: string;} |
|
|
239
|
+
{type: 'Unit' | 'Null' | 'Undefined';} |
|
|
240
|
+
{type: 'Nullable' | 'Optional'; value: ScalarValue | null;};
|
|
241
|
+
|
|
242
|
+
export interface Compiler {
|
|
243
|
+
check(input: CheckRequest): Promise<Result>;
|
|
244
|
+
expand(input: CheckRequest): Promise<Result>;
|
|
245
|
+
planGeneration(input: GenerationRequest): Promise<Result>;
|
|
246
|
+
}
|
|
247
|
+
|
|
29
248
|
export function createCompiler(): Promise<Compiler>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lawspec",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "State the law once. Check it everywhere.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
"bin": { "lawspec": "bin/lawspec.mjs" },
|
|
9
9
|
"exports": { ".": { "types": "./index.d.ts", "import": "./api.mjs" } },
|
|
10
10
|
"types": "index.d.ts",
|
|
11
|
-
"files": ["*.mjs", "*.json", "index.d.ts", "bin", "core.wasm", "core_jsffi.js", "README.md", "PRIMITIVES.md", "REFINEMENTS.md", "RUST.md", "LANGUAGE.md", "API-MIGRATION.md", "LICENSE", "starter.lawspec", "examples"],
|
|
11
|
+
"files": ["*.mjs", "*.json", "index.d.ts", "bin", "core.wasm", "core_jsffi.js", "README.md", "PRIMITIVES.md", "REFINEMENTS.md", "RUST.md", "JAVA.md", "PYTHON.md", "GO.md", "HASKELL.md", "KOTLIN.md", "WEB.md", "LANGUAGE.md", "API-MIGRATION.md", "RELEASE-0.9.md", "LICENSE", "starter.lawspec", "examples"],
|
|
12
12
|
"scripts": { "test": "node --test test/*.test.mjs" }
|
|
13
13
|
}
|
package/templates.mjs
CHANGED
|
@@ -34,8 +34,97 @@ export const setup = {
|
|
|
34
34
|
kotlin:
|
|
35
35
|
"Use JDK 25, Gradle 9.3.0, Kotlin plugin 2.3.21, JVM target 25, Kotest 5.9.1 (runner, assertions, property), and useJUnitPlatform(). Run gradle testClasses.",
|
|
36
36
|
};
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
// These render known scaffold structure; they never reformat user source.
|
|
38
|
+
const element = (name, value, attributes = {}) => ({ name, value, attributes });
|
|
39
|
+
const xmlEscape = (text) =>
|
|
40
|
+
String(text)
|
|
41
|
+
.replaceAll("&", "&")
|
|
42
|
+
.replaceAll('"', """)
|
|
43
|
+
.replaceAll("<", "<")
|
|
44
|
+
.replaceAll(">", ">");
|
|
45
|
+
function renderXml(node, minify, depth = 0) {
|
|
46
|
+
const indent = minify ? "" : " ".repeat(depth);
|
|
47
|
+
const attributes = Object.entries(node.attributes).map(
|
|
48
|
+
([key, value]) => `${key}="${xmlEscape(value)}"`,
|
|
49
|
+
);
|
|
50
|
+
const open = `<${node.name}${
|
|
51
|
+
attributes.length === 0
|
|
52
|
+
? ""
|
|
53
|
+
: minify
|
|
54
|
+
? " " + attributes.join(" ")
|
|
55
|
+
: "\n" + attributes.map((a) => indent + " " + a).join("\n")
|
|
56
|
+
}>`;
|
|
57
|
+
if (!Array.isArray(node.value)) {
|
|
58
|
+
return `${indent}${open}${xmlEscape(node.value)}</${node.name}>`;
|
|
59
|
+
}
|
|
60
|
+
const children = node.value.map((child) =>
|
|
61
|
+
renderXml(child, minify, depth + 1),
|
|
62
|
+
);
|
|
63
|
+
return minify
|
|
64
|
+
? `${open}${children.join("")}</${node.name}>`
|
|
65
|
+
: `${indent}${open}\n${children.join("\n")}\n${indent}</${node.name}>`;
|
|
66
|
+
}
|
|
67
|
+
function mavenProject(minify) {
|
|
68
|
+
const fields = (values) =>
|
|
69
|
+
Object.entries(values).map(([name, value]) => element(name, value));
|
|
70
|
+
const dependency = (groupId, artifactId, version) =>
|
|
71
|
+
element(
|
|
72
|
+
"dependency",
|
|
73
|
+
fields({ groupId, artifactId, version, scope: "test" }),
|
|
74
|
+
);
|
|
75
|
+
const plugin = (artifactId, version) =>
|
|
76
|
+
element(
|
|
77
|
+
"plugin",
|
|
78
|
+
fields({ groupId: "org.apache.maven.plugins", artifactId, version }),
|
|
79
|
+
);
|
|
80
|
+
return (
|
|
81
|
+
renderXml(
|
|
82
|
+
element(
|
|
83
|
+
"project",
|
|
84
|
+
[
|
|
85
|
+
...fields({
|
|
86
|
+
modelVersion: "4.0.0",
|
|
87
|
+
groupId: "example",
|
|
88
|
+
artifactId: "lawspec-example",
|
|
89
|
+
version: "0.1.0",
|
|
90
|
+
}),
|
|
91
|
+
element(
|
|
92
|
+
"properties",
|
|
93
|
+
fields({
|
|
94
|
+
"maven.compiler.release": "25",
|
|
95
|
+
"project.build.sourceEncoding": "UTF-8",
|
|
96
|
+
}),
|
|
97
|
+
),
|
|
98
|
+
element("dependencies", [
|
|
99
|
+
dependency("org.jetbrains", "jetCheck", "0.3.0"),
|
|
100
|
+
dependency("org.junit.jupiter", "junit-jupiter", "5.14.0"),
|
|
101
|
+
]),
|
|
102
|
+
element("build", [
|
|
103
|
+
element("plugins", [
|
|
104
|
+
plugin("maven-compiler-plugin", "3.14.1"),
|
|
105
|
+
plugin("maven-surefire-plugin", "3.5.4"),
|
|
106
|
+
]),
|
|
107
|
+
]),
|
|
108
|
+
],
|
|
109
|
+
{
|
|
110
|
+
xmlns: "http://maven.apache.org/POM/4.0.0",
|
|
111
|
+
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
|
|
112
|
+
"xsi:schemaLocation":
|
|
113
|
+
"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd",
|
|
114
|
+
},
|
|
115
|
+
),
|
|
116
|
+
minify,
|
|
117
|
+
) + "\n"
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
export function templates(target, { minify = false } = {}) {
|
|
121
|
+
if (typeof minify !== "boolean") throw new Error("minify must be a boolean");
|
|
122
|
+
const json = (value) =>
|
|
123
|
+
JSON.stringify(value, null, minify ? undefined : 2) + "\n";
|
|
124
|
+
const kotlinBlock = (name, statements) =>
|
|
125
|
+
minify
|
|
126
|
+
? `${name} { ${statements.join("; ")} }`
|
|
127
|
+
: `${name} {\n${statements.map((line) => " " + line).join("\n")}\n}`;
|
|
39
128
|
if (!targets.includes(target)) throw new Error(`Unknown target: ${target}`);
|
|
40
129
|
const commonPackage = {
|
|
41
130
|
name: "lawspec-example",
|
|
@@ -46,7 +135,8 @@ export function templates(target) {
|
|
|
46
135
|
switch (target) {
|
|
47
136
|
case "rust":
|
|
48
137
|
return {
|
|
49
|
-
"src/lib.rs":
|
|
138
|
+
"src/lib.rs":
|
|
139
|
+
'// Application library. LawSpec maintains the included module declarations.\ninclude!("lawspec_modules.rs");\n',
|
|
50
140
|
"Cargo.toml": `[package]
|
|
51
141
|
name = "lawspec-example"
|
|
52
142
|
version = "0.1.0"
|
|
@@ -103,18 +193,7 @@ proptest = "=1.11.0"
|
|
|
103
193
|
};
|
|
104
194
|
case "java":
|
|
105
195
|
return {
|
|
106
|
-
"pom.xml":
|
|
107
|
-
<modelVersion>4.0.0</modelVersion><groupId>example</groupId><artifactId>lawspec-example</artifactId><version>0.1.0</version>
|
|
108
|
-
<properties><maven.compiler.release>25</maven.compiler.release><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties>
|
|
109
|
-
<dependencies>
|
|
110
|
-
<dependency><groupId>org.jetbrains</groupId><artifactId>jetCheck</artifactId><version>0.3.0</version><scope>test</scope></dependency>
|
|
111
|
-
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.14.0</version><scope>test</scope></dependency>
|
|
112
|
-
</dependencies>
|
|
113
|
-
<build><plugins>
|
|
114
|
-
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.14.1</version></plugin>
|
|
115
|
-
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>3.5.4</version></plugin>
|
|
116
|
-
</plugins></build>
|
|
117
|
-
</project>\n`,
|
|
196
|
+
"pom.xml": mavenProject(minify),
|
|
118
197
|
};
|
|
119
198
|
case "go":
|
|
120
199
|
return {
|
|
@@ -124,13 +203,24 @@ proptest = "=1.11.0"
|
|
|
124
203
|
case "haskell":
|
|
125
204
|
return {
|
|
126
205
|
"stack.yaml": "snapshot: lts-24.58\npackages: [.]\n",
|
|
127
|
-
"package.yaml": `name: lawspec-example\nversion: 0.1.0\ndependencies: [base, text, bytestring]\nlibrary:\n source-dirs: src\ntests:\n laws:\n main: Spec.hs\n source-dirs: test\n dependencies: [lawspec-example, hspec, hedgehog, hspec-hedgehog]\n build-tools: [hspec-discover]\n`,
|
|
206
|
+
"package.yaml": `name: lawspec-example\nversion: 0.1.0\ndependencies: [base, text, bytestring]\nlibrary:\n source-dirs: src\ntests:\n laws:\n main: Spec.hs\n source-dirs: test\n dependencies: [lawspec-example, hspec, hedgehog, hspec-hedgehog, containers, mtl]\n build-tools: [hspec-discover]\n`,
|
|
128
207
|
"test/Spec.hs": "{-# OPTIONS_GHC -F -pgmF hspec-discover #-}\n",
|
|
129
208
|
};
|
|
130
209
|
case "kotlin":
|
|
131
210
|
return {
|
|
132
211
|
"settings.gradle.kts": 'rootProject.name = "lawspec-example"\n',
|
|
133
|
-
"build.gradle.kts":
|
|
212
|
+
"build.gradle.kts":
|
|
213
|
+
[
|
|
214
|
+
kotlinBlock("plugins", ['kotlin("jvm") version "2.3.21"']),
|
|
215
|
+
kotlinBlock("repositories", ["mavenCentral()"]),
|
|
216
|
+
kotlinBlock("kotlin", ["jvmToolchain(25)"]),
|
|
217
|
+
kotlinBlock("dependencies", [
|
|
218
|
+
'testImplementation("io.kotest:kotest-runner-junit5:5.9.1")',
|
|
219
|
+
'testImplementation("io.kotest:kotest-assertions-core:5.9.1")',
|
|
220
|
+
'testImplementation("io.kotest:kotest-property:5.9.1")',
|
|
221
|
+
]),
|
|
222
|
+
kotlinBlock("tasks.test", ["useJUnitPlatform()"]),
|
|
223
|
+
].join(minify ? "\n" : "\n\n") + "\n",
|
|
134
224
|
};
|
|
135
225
|
}
|
|
136
226
|
}
|