diff --git a/packages/concerto-core/lib/introspect/parser.js b/packages/concerto-core/lib/introspect/parser.js index 04d68277e1..f8e62a89f4 100644 --- a/packages/concerto-core/lib/introspect/parser.js +++ b/packages/concerto-core/lib/introspect/parser.js @@ -264,15 +264,10 @@ function peg$parse(input, options) { peg$c105 = "/", peg$c106 = peg$literalExpectation("/", false), peg$c107 = function(pattern, flags) { - var value; - - try { - value = new RegExp(pattern, flags); - } catch (e) { - error(e.message); - } - - return { type: "Literal", value: value }; + return { + pattern, + flags + }; }, peg$c108 = /^[*\\\/[]/, peg$c109 = peg$classExpectation(["*", "\\", "/", "["], false, false), @@ -9195,7 +9190,7 @@ function peg$parse(input, options) { } function peg$parseStringRegexValidator() { - var s0, s1, s2, s3, s4, s5, s6; + var s0, s1, s2, s3, s4, s5; s0 = peg$currPos; if (input.substr(peg$currPos, 5) === peg$c302) { @@ -9218,13 +9213,7 @@ function peg$parse(input, options) { if (s3 !== peg$FAILED) { s4 = peg$parse__(); if (s4 !== peg$FAILED) { - s5 = peg$currPos; - s6 = peg$parseRegularExpressionLiteral(); - if (s6 !== peg$FAILED) { - s5 = input.substring(s5, peg$currPos); - } else { - s5 = s6; - } + s5 = peg$parseRegularExpressionLiteral(); if (s5 !== peg$FAILED) { peg$savedPos = s0; s1 = peg$c304(s5); diff --git a/packages/concerto-core/lib/introspect/parser.pegjs b/packages/concerto-core/lib/introspect/parser.pegjs index 826670f713..ddd4e962fe 100644 --- a/packages/concerto-core/lib/introspect/parser.pegjs +++ b/packages/concerto-core/lib/introspect/parser.pegjs @@ -283,15 +283,10 @@ UnicodeEscapeSequence RegularExpressionLiteral "regular expression" = "/" pattern:$RegularExpressionBody "/" flags:$RegularExpressionFlags { - var value; - - try { - value = new RegExp(pattern, flags); - } catch (e) { - error(e.message); - } - - return { type: "Literal", value: value }; + return { + pattern, + flags + }; } RegularExpressionBody @@ -1037,7 +1032,7 @@ StringFieldDeclaration } StringRegexValidator - = "regex" __ "=" __ regex:$RegularExpressionLiteral { + = "regex" __ "=" __ regex:RegularExpressionLiteral { return regex } diff --git a/packages/concerto-core/lib/introspect/stringvalidator.js b/packages/concerto-core/lib/introspect/stringvalidator.js index 6a5a16503a..c11c7ce934 100644 --- a/packages/concerto-core/lib/introspect/stringvalidator.js +++ b/packages/concerto-core/lib/introspect/stringvalidator.js @@ -33,10 +33,13 @@ class StringValidator extends Validator{ * @throws {IllegalModelException} */ constructor(field, validator) { - super(field,validator); + super(field, validator); try { - // discard the leading / and closing / - this.regex = new RegExp(validator.substring(1,validator.length-1)); + if (validator.flags) { + this.regex = new RegExp(validator.pattern, validator.flags); + } else { + this.regex = new RegExp(validator.pattern); + } } catch(exception) { this.reportError(exception.message); @@ -53,7 +56,7 @@ class StringValidator extends Validator{ validate(identifier, value) { if(value !== null) { if(!this.regex.test(value)) { - this.reportError(identifier, 'Value + \'' + value + '\' failed to match validation regex: ' + this.regex); + this.reportError(identifier, 'Value \'' + value + '\' failed to match validation regex: ' + this.regex); } } } diff --git a/packages/concerto-core/test/introspect/field.js b/packages/concerto-core/test/introspect/field.js index f068bb38c4..6022f34dd8 100644 --- a/packages/concerto-core/test/introspect/field.js +++ b/packages/concerto-core/test/introspect/field.js @@ -43,7 +43,7 @@ describe('Field', () => { should.equal(f.validator, null); }); - it('should save the incoming validator', () => { + it('should save the incoming string validator', () => { let f = new Field(mockClassDeclaration, { id: { @@ -52,7 +52,21 @@ describe('Field', () => { propertyType: { name: 'String' }, - regex: 'suchValidator' + regex: '/^suchValidator$/' + }); + f.getValidator().validate('id', 'suchValidator'); + }); + + it('should save the incoming string validator (with flag)', () => { + + let f = new Field(mockClassDeclaration, { + id: { + name: 'field', + }, + propertyType: { + name: 'String' + }, + regex: '/^suchValidator$/u' }); f.getValidator().validate('id', 'suchValidator'); }); diff --git a/packages/concerto-core/test/introspect/stringvalidator.js b/packages/concerto-core/test/introspect/stringvalidator.js index ffb26ad9bf..395351e6e4 100644 --- a/packages/concerto-core/test/introspect/stringvalidator.js +++ b/packages/concerto-core/test/introspect/stringvalidator.js @@ -33,7 +33,7 @@ describe('StringValidator', () => { it('should throw for invalid regexes', () => { (() => { - new StringValidator(mockField, '/^[A-z/' ); + new StringValidator(mockField, { pattern: '^[A-z' }); }).should.throw(/Validator error for field/); }); @@ -42,22 +42,47 @@ describe('StringValidator', () => { describe('#validate', () => { it('should ignore a null string', () => { - let v = new StringValidator(mockField, '/^[A-z][A-z][0-9]{7}/' ); + let v = new StringValidator(mockField, { pattern: '^[A-z][A-z][0-9]{7}' }); v.getRegex().toString().should.equal('/^[A-z][A-z][0-9]{7}/'); v.validate('id', null); }); it('should validate a string', () => { - let v = new StringValidator(mockField, '/^[A-z][A-z][0-9]{7}/' ); + let v = new StringValidator(mockField, { pattern: '^[A-z][A-z][0-9]{7}' }); v.validate('id', 'AB1234567'); }); it('should detect mismatch string', () => { - let v = new StringValidator(mockField, '/^[A-z][A-z][0-9]{7}/'); + let v = new StringValidator(mockField, { pattern: '^[A-z][A-z][0-9]{7}' }); (() => { v.validate('id', 'xyz'); }).should.throw(/Validator error for field id org.acme.myField/); }); + + it('should validate a string with escaped chacters', () => { + let v = new StringValidator(mockField, { pattern: '^[\\\\]*\\n$' }); + v.validate('id', '\\\\\n'); + }); + + it('should not validate a string with escaped chacters', () => { + let v = new StringValidator(mockField, { pattern: '^[\\\\]*\\n$' }); + (() => { + v.validate('id', '\\hi!\n'); + }).should.throw(/Validator error for field id org.acme.myField/); + }); + + it('should validate a unicode string', () => { + let v = new StringValidator(mockField, { pattern: '^(?!null|true|false)(\\p{Lu}|\\p{Ll}|\\p{Lt}|\\p{Lm}|\\p{Lo}|\\p{Nl}|\\$|_|\\\\u[0-9A-Fa-f]{4})(?:\\p{Lu}|\\p{Ll}|\\p{Lt}|\\p{Lm}|\\p{Lo}|\\p{Nl}|\\$|_|\\\\u[0-9A-Fa-f]{4}|\\p{Mn}|\\p{Mc}|\\p{Nd}|\\p{Pc}|\\u200C|\\u200D)*$', flags: 'u' }); + v.validate('id', 'AB1234567'); + }); + + it('should not validate a unicode string', () => { + let v = new StringValidator(mockField, { pattern: '^(?!null|true|false)(\\p{Lu}|\\p{Ll}|\\p{Lt}|\\p{Lm}|\\p{Lo}|\\p{Nl}|\\$|_|\\\\u[0-9A-Fa-f]{4})(?:\\p{Lu}|\\p{Ll}|\\p{Lt}|\\p{Lm}|\\p{Lo}|\\p{Nl}|\\$|_|\\\\u[0-9A-Fa-f]{4}|\\p{Mn}|\\p{Mc}|\\p{Nd}|\\p{Pc}|\\u200C|\\u200D)*$', flags: 'u' }); + (() => { + v.validate('id', '1FOO'); + }).should.throw(/Validator error for field id org.acme.myField/); + }); + }); });