Skip to content

Commit 82d778c

Browse files
authored
enum inline fixes (#190)
1 parent d54008b commit 82d778c

4 files changed

Lines changed: 56 additions & 64 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
function startsConstraint(trimmedLine) {
2+
return /^IF\s+(?:\[|\(|NOT\b)/i.test(trimmedLine);
3+
}
4+
5+
function looksLikeInlineRuleSpec(ruleText) {
6+
const trimmed = String(ruleText ?? '').trim();
7+
if (trimmed.length === 0 || startsConstraint(trimmed)) {
8+
return false;
9+
}
10+
11+
if (
12+
/^(?:enum|literal|regex|datatype\.(?:enum|literal|regex)|awd\.datatype\.(?:enum|literal|regex))\s*\(/i.test(trimmed)
13+
) {
14+
return true;
15+
}
16+
17+
if (/^(?:faker\.)?[A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z][A-Za-z0-9_]*)+(?:\s*\(.*\)\s*|\s*)$/i.test(trimmed)) {
18+
return true;
19+
}
20+
21+
if (!trimmed.includes(',')) {
22+
return false;
23+
}
24+
25+
const values = trimmed.split(',').map((value) => value.trim());
26+
if (values.length < 2 || values.some((value) => value.length === 0 || value.length > 50)) {
27+
return false;
28+
}
29+
30+
return !values.some((value) => /[[\]{}()^$*+?|\\]/.test(value) || (value.includes('.') && /[A-Z]/.test(value)));
31+
}
32+
33+
export { startsConstraint, looksLikeInlineRuleSpec };

packages/core/js/data_generation/rulesParser.js

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,7 @@
11
import { TestDataRules } from './testDataRules.js';
22
import { SchemaParsingErrors } from './schema-parsing-errors.js';
33
import { parseConstraintText } from './schema-constraint-parser.js';
4-
5-
function startsConstraint(trimmedLine) {
6-
return /^IF\s+(?:\[|\(|NOT\b)/i.test(trimmedLine);
7-
}
8-
9-
function looksLikeInlineRuleSpec(ruleText) {
10-
const trimmed = String(ruleText ?? '').trim();
11-
if (trimmed.length === 0 || startsConstraint(trimmed)) {
12-
return false;
13-
}
14-
15-
if (
16-
/^(?:enum|literal|regex|datatype\.(?:enum|literal|regex)|awd\.datatype\.(?:enum|literal|regex))\s*\(/i.test(trimmed)
17-
) {
18-
return true;
19-
}
20-
21-
if (/^(?:faker\.)?[A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z][A-Za-z0-9_]*)+(?:\s*\(.*\)\s*|\s*)$/i.test(trimmed)) {
22-
return true;
23-
}
24-
25-
if (!trimmed.includes(',')) {
26-
return false;
27-
}
28-
29-
const values = trimmed.split(',').map((value) => value.trim());
30-
if (values.length < 2 || values.some((value) => value.length === 0 || value.length > 50)) {
31-
return false;
32-
}
33-
34-
return !values.some((value) => /[[\]{}()^$*+?|\\]/.test(value) || (value.includes('.') && /[A-Z]/.test(value)));
35-
}
4+
import { looksLikeInlineRuleSpec, startsConstraint } from './inline-schema-rule.js';
365

376
function parseInlineRuleDefinition(line) {
387
const source = String(line ?? '');
@@ -42,15 +11,18 @@ function parseInlineRuleDefinition(line) {
4211
}
4312

4413
const name = source.slice(0, index).trim();
45-
const rule = source.slice(index + 1).trim();
14+
const rawRulePortion = source.slice(index + 1);
15+
const rule = rawRulePortion.trim();
4616
if (name.length === 0 || !looksLikeInlineRuleSpec(rule)) {
4717
continue;
4818
}
4919

20+
const leadingWhitespaceLength = rawRulePortion.length - rawRulePortion.trimStart().length;
21+
5022
return {
5123
name,
5224
rule,
53-
separator: ': ',
25+
separator: `:${rawRulePortion.slice(0, leadingWhitespaceLength)}`,
5426
};
5527
}
5628

packages/core/src/index.js

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
CombinationAlgorithm,
1212
CombinationsTestDataGenerator,
1313
} from '../js/data_generation/n-wise/combinationsTestDataGenerator.js';
14+
import { looksLikeInlineRuleSpec, startsConstraint } from '../js/data_generation/inline-schema-rule.js';
1415
import { parseSchemaText } from '../js/data_generation/schema-conversion.js';
1516
import { hasSafeFakerLiteralArguments } from '../js/data_generation/faker/safeLiteralArgumentParser.js';
1617
import {
@@ -78,34 +79,6 @@ const SUPPORTED_FORMATS = [
7879
'asciitable',
7980
];
8081

81-
function looksLikeInlineSchemaRule(ruleText) {
82-
const trimmed = String(ruleText ?? '').trim();
83-
if (trimmed.length === 0 || /^IF\s+(?:\[|\(|NOT\b)/i.test(trimmed)) {
84-
return false;
85-
}
86-
87-
if (
88-
/^(?:enum|literal|regex|datatype\.(?:enum|literal|regex)|awd\.datatype\.(?:enum|literal|regex))\s*\(/i.test(trimmed)
89-
) {
90-
return true;
91-
}
92-
93-
if (/^(?:faker\.)?[A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z][A-Za-z0-9_]*)+(?:\s*\(.*\)\s*|\s*)$/i.test(trimmed)) {
94-
return true;
95-
}
96-
97-
if (!trimmed.includes(',')) {
98-
return false;
99-
}
100-
101-
const values = trimmed.split(',').map((value) => value.trim());
102-
if (values.length < 2 || values.some((value) => value.length === 0 || value.length > 50)) {
103-
return false;
104-
}
105-
106-
return !values.some((value) => /[[\]{}()^$*+?|\\]/.test(value) || (value.includes('.') && /[A-Z]/.test(value)));
107-
}
108-
10982
function extractRuleLines(textSpec) {
11083
if (typeof textSpec !== 'string') {
11184
return [];
@@ -115,7 +88,7 @@ function extractRuleLines(textSpec) {
11588
let pendingName = null;
11689
for (const line of lines) {
11790
const trimmed = line.trim();
118-
if (trimmed.length === 0 || /^\s*#/.test(line) || /^IF\s+(?:\[|\(|NOT\b)/i.test(trimmed)) {
91+
if (trimmed.length === 0 || /^\s*#/.test(line) || startsConstraint(trimmed)) {
11992
pendingName = null;
12093
continue;
12194
}
@@ -126,7 +99,7 @@ function extractRuleLines(textSpec) {
12699
continue;
127100
}
128101
const rule = line.slice(separatorIndex + 1).trim();
129-
if (looksLikeInlineSchemaRule(rule)) {
102+
if (looksLikeInlineRuleSpec(rule)) {
130103
ruleLines.push(rule);
131104
pendingName = null;
132105
matchedInlineRule = true;

packages/core/src/tests/data_generation/unit/rulesParser.test.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,20 @@ Status: person.jobTitle`;
140140
expect(parser.renderSpecFromRulesWithTokens(parser.testDataRules.rules)).toBe(inputText);
141141
});
142142

143+
test('preserves authored inline separator spacing when rebuilding from parsed tokens', () => {
144+
const inputText = `Name:person.fullName
145+
Role: enum(admin,user)`;
146+
147+
const parser = new RulesParser(faker, RandExp);
148+
parser.parseText(inputText);
149+
150+
expect(parser.getSchemaTokens()).toEqual([
151+
expect.objectContaining({ kind: 'rule', separator: ':' }),
152+
expect.objectContaining({ kind: 'rule', separator: ': ' }),
153+
]);
154+
expect(parser.renderSpecFromRulesWithTokens(parser.testDataRules.rules)).toBe(inputText);
155+
});
156+
143157
test('preserves comments and blank lines when rebuilding from rule comments', () => {
144158
const inputText = `# one
145159

0 commit comments

Comments
 (0)