harmonyc 0.11.2 → 0.12.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/code_generator/VitestGenerator.js +9 -3
- package/model/model.js +11 -4
- package/package.json +1 -1
- package/parser/lexer.js +2 -2
- package/parser/parser.js +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { basename } from 'path';
|
|
2
|
-
import { Arg, Word, } from "../model/model.js";
|
|
2
|
+
import { Arg, Response, Word, } from "../model/model.js";
|
|
3
3
|
export class VitestGenerator {
|
|
4
4
|
constructor(tf, sf) {
|
|
5
5
|
this.tf = tf;
|
|
@@ -113,16 +113,22 @@ export class VitestGenerator {
|
|
|
113
113
|
const f = this.featureVars.get(p.feature.name);
|
|
114
114
|
const args = p.args.map((a) => a.toCode(this));
|
|
115
115
|
args.push(...this.extraArgs);
|
|
116
|
+
if (p instanceof Response && p.parts.length === 1 && p.saveToVariable) {
|
|
117
|
+
return this.saveToVariable(p.saveToVariable);
|
|
118
|
+
}
|
|
116
119
|
this.tf.print(`(context.task.meta.phrases.push(${str(p.toString())}),`);
|
|
120
|
+
if (p instanceof Response && p.saveToVariable) {
|
|
121
|
+
this.saveToVariable(p.saveToVariable, '');
|
|
122
|
+
}
|
|
117
123
|
this.tf.print(`await ${f}.${functionName(p)}(${args.join(', ')}));`);
|
|
118
124
|
}
|
|
119
125
|
setVariable(action) {
|
|
120
126
|
this.tf.print(`(context.task.meta.variables ??= {})[${str(action.variableName)}] = ${action.value.toCode(this)};`);
|
|
121
127
|
}
|
|
122
|
-
saveToVariable(s) {
|
|
128
|
+
saveToVariable(s, what = this.extraArgs[0] + ';') {
|
|
123
129
|
if (this.extraArgs.length !== 1)
|
|
124
130
|
return;
|
|
125
|
-
this.tf.print(`(context.task.meta.variables ??= {})[${str(s.variableName)}] = ${
|
|
131
|
+
this.tf.print(`(context.task.meta.variables ??= {})[${str(s.variableName)}] = ${what}`.trimEnd());
|
|
126
132
|
}
|
|
127
133
|
stringLiteral(text, { withVariables }) {
|
|
128
134
|
if (withVariables && text.match(/\$\{/)) {
|
package/model/model.js
CHANGED
|
@@ -256,10 +256,14 @@ export class Action extends Phrase {
|
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
export class Response extends Phrase {
|
|
259
|
-
constructor() {
|
|
260
|
-
super(...
|
|
259
|
+
constructor(parts, saveToVariable) {
|
|
260
|
+
super([...parts, ...(saveToVariable ? [saveToVariable] : [])]);
|
|
261
|
+
this.saveToVariable = saveToVariable;
|
|
261
262
|
this.kind = 'response';
|
|
262
263
|
}
|
|
264
|
+
get isEmpty() {
|
|
265
|
+
return this.parts.length === 0 && !this.saveToVariable;
|
|
266
|
+
}
|
|
263
267
|
toString() {
|
|
264
268
|
return `=> ${super.toString()}`;
|
|
265
269
|
}
|
|
@@ -288,14 +292,17 @@ export class SetVariable extends Action {
|
|
|
288
292
|
cg.setVariable(this);
|
|
289
293
|
}
|
|
290
294
|
}
|
|
291
|
-
export class SaveToVariable extends
|
|
295
|
+
export class SaveToVariable extends Part {
|
|
292
296
|
constructor(variableName) {
|
|
293
|
-
super(
|
|
297
|
+
super();
|
|
294
298
|
this.variableName = variableName;
|
|
295
299
|
}
|
|
296
300
|
toCode(cg) {
|
|
297
301
|
cg.saveToVariable(this);
|
|
298
302
|
}
|
|
303
|
+
toString() {
|
|
304
|
+
return `\${${this.variableName}}`;
|
|
305
|
+
}
|
|
299
306
|
}
|
|
300
307
|
export class Precondition extends Branch {
|
|
301
308
|
constructor(state = '') {
|
package/package.json
CHANGED
package/parser/lexer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TokenError } from 'typescript-parsec';
|
|
2
|
-
import rules from
|
|
3
|
-
export { T } from
|
|
2
|
+
import rules from './lexer_rules.js';
|
|
3
|
+
export { T } from './lexer_rules.js';
|
|
4
4
|
// based on https://github.com/microsoft/ts-parsec/blob/3350fcb/packages/ts-parsec/src/Lexer.ts
|
|
5
5
|
/*
|
|
6
6
|
MIT License
|
package/parser/parser.js
CHANGED
|
@@ -5,7 +5,7 @@ export function parse(input, production = TEST_DESIGN) {
|
|
|
5
5
|
const tokens = lexer.parse(input);
|
|
6
6
|
return expectSingleResult(expectEOF(production.parse(tokens)));
|
|
7
7
|
}
|
|
8
|
-
export const NEWLINES = list_sc(tok(T.Newline), nil()), WORDS = apply(tok(T.Words), ({ text }) => new Word(text.trimEnd().split(/\s+/).join(' '))), DOUBLE_QUOTE_STRING = alt_sc(apply(tok(T.DoubleQuoteString), ({ text }) => new StringLiteral(JSON.parse(text))), seq(tok(T.UnclosedDoubleQuoteString), fail('unclosed double-quote string'))), BACKTICK_STRING = apply(tok(T.BacktickString), ({ text }) => new CodeLiteral(text.slice(1, -1))), DOCSTRING = kright(opt_sc(NEWLINES), apply(list_sc(tok(T.MultilineString), tok(T.Newline)), (lines) => new Docstring(lines.map(({ text }) => text.slice(2)).join('\n')))), ERROR_MARK = tok(T.ErrorMark), VARIABLE = apply(tok(T.Variable), ({ text }) => text.slice(2, -1)), PART = alt_sc(WORDS, DOUBLE_QUOTE_STRING, BACKTICK_STRING, DOCSTRING), PHRASE = rep_sc(PART), ARG = alt_sc(DOUBLE_QUOTE_STRING, BACKTICK_STRING, DOCSTRING), SET_VARIABLE = apply(seq(VARIABLE, ARG), ([variable, value]) => new SetVariable(variable, value)), ACTION = alt_sc(SET_VARIABLE, apply(PHRASE, (parts) => new Action(parts))), RESPONSE = apply(PHRASE, (parts) => new Response(parts)), ERROR_RESPONSE = apply(seq(ERROR_MARK, opt_sc(alt_sc(DOUBLE_QUOTE_STRING, DOCSTRING))), ([, parts]) => new ErrorResponse(parts)), SAVE_TO_VARIABLE = apply(VARIABLE, (variable) => new SaveToVariable(variable)), ARROW = kright(opt_sc(NEWLINES), tok(T.ResponseArrow)), RESPONSE_ITEM = kright(ARROW, alt_sc(SAVE_TO_VARIABLE, ERROR_RESPONSE, RESPONSE)), STEP = apply(seq(ACTION, rep_sc(RESPONSE_ITEM)), ([action, responses]) => new Step(action, responses).setFork(true)), LABEL = apply(kleft(list_sc(PART, nil()), tok(T.Colon)), (words) => new Label(words.map((w) => w.toString()).join(' '))), SECTION = apply(LABEL, (text) => new Section(text)), BRANCH = alt_sc(SECTION, STEP), // section first, to make sure there is no colon after step
|
|
8
|
+
export const NEWLINES = list_sc(tok(T.Newline), nil()), WORDS = apply(tok(T.Words), ({ text }) => new Word(text.trimEnd().split(/\s+/).join(' '))), DOUBLE_QUOTE_STRING = alt_sc(apply(tok(T.DoubleQuoteString), ({ text }) => new StringLiteral(JSON.parse(text))), seq(tok(T.UnclosedDoubleQuoteString), fail('unclosed double-quote string'))), BACKTICK_STRING = apply(tok(T.BacktickString), ({ text }) => new CodeLiteral(text.slice(1, -1))), DOCSTRING = kright(opt_sc(NEWLINES), apply(list_sc(tok(T.MultilineString), tok(T.Newline)), (lines) => new Docstring(lines.map(({ text }) => text.slice(2)).join('\n')))), ERROR_MARK = tok(T.ErrorMark), VARIABLE = apply(tok(T.Variable), ({ text }) => text.slice(2, -1)), PART = alt_sc(WORDS, DOUBLE_QUOTE_STRING, BACKTICK_STRING, DOCSTRING), PHRASE = rep_sc(PART), ARG = alt_sc(DOUBLE_QUOTE_STRING, BACKTICK_STRING, DOCSTRING), SET_VARIABLE = apply(seq(VARIABLE, ARG), ([variable, value]) => new SetVariable(variable, value)), ACTION = alt_sc(SET_VARIABLE, apply(PHRASE, (parts) => new Action(parts))), RESPONSE = apply(seq(PHRASE, opt_sc(VARIABLE)), ([parts, variable]) => new Response(parts, variable !== undefined ? new SaveToVariable(variable) : undefined)), ERROR_RESPONSE = apply(seq(ERROR_MARK, opt_sc(alt_sc(DOUBLE_QUOTE_STRING, DOCSTRING))), ([, parts]) => new ErrorResponse(parts)), SAVE_TO_VARIABLE = apply(VARIABLE, (variable) => new Response([], new SaveToVariable(variable))), ARROW = kright(opt_sc(NEWLINES), tok(T.ResponseArrow)), RESPONSE_ITEM = kright(ARROW, alt_sc(SAVE_TO_VARIABLE, ERROR_RESPONSE, RESPONSE)), STEP = apply(seq(ACTION, rep_sc(RESPONSE_ITEM)), ([action, responses]) => new Step(action, responses).setFork(true)), LABEL = apply(kleft(list_sc(PART, nil()), tok(T.Colon)), (words) => new Label(words.map((w) => w.toString()).join(' '))), SECTION = apply(LABEL, (text) => new Section(text)), BRANCH = alt_sc(SECTION, STEP), // section first, to make sure there is no colon after step
|
|
9
9
|
DENTS = apply(alt_sc(tok(T.Plus), tok(T.Minus)), (seqOrFork) => {
|
|
10
10
|
return {
|
|
11
11
|
dent: (seqOrFork.text.length - 2) / 2,
|