Skip to content

Commit

Permalink
Merge pull request #83 from firebase/koss-quoted-property-names
Browse files Browse the repository at this point in the history
Allow quoted property names - fixes issue #38 and #81.
  • Loading branch information
mckoss committed Nov 20, 2015
2 parents 84901da + f582f0b commit 4a8a54c
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
changed - Support string.test(/regexp/) format (formerly required regexp in a quoted string).
feature - Added regexp test and samples.
feature - Allow quoted property names in type statements.
fixed - Parser failed when empty string used.
10 changes: 10 additions & 0 deletions src/rules-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@ var errors = {
invalidGeneric: "Invalid generic schema usage: ",
invalidMapKey: "Map<Key, T> - Key must derive from String type.",
invalidWildChildren: "Types can have at most one $wild property and cannot mix with other properties.",
invalidPropertyName: "Property names cannot contain any of: . $ # [ ] / or control characters: ",
};

let INVALID_KEY_REGEX = /[\[\].#$\/\u0000-\u001F\u007F]/;

/*
A Validator is a JSON heriarchical structure. The "leaves" are "dot-properties"
(see below). The intermediate nodes in the tree are "prop" or "$prop"
Expand Down Expand Up @@ -418,6 +421,13 @@ export class Generator {
Object.keys(schema.properties).forEach((propName) => {
if (propName[0] === '$') {
wildProperties += 1;
if (INVALID_KEY_REGEX.test(propName.slice(1))) {
this.fatal(errors.invalidPropertyName + propName);
}
} else {
if (INVALID_KEY_REGEX.test(propName)) {
this.fatal(errors.invalidPropertyName + propName);
}
}
if (!validator[propName]) {
validator[propName] = {};
Expand Down
10 changes: 6 additions & 4 deletions src/rules-parser.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ Properties = head:PropertyDefinition tail:(_ PropSep part:PropertyDefinition { r

PropSep = ("," / ";")? _

PropertyDefinition = name:Identifier _ ":" _ type:TypeExpression {
PropertyDefinition = name:(Identifier / String) _ ":" _ type:TypeExpression {
return {
name: name,
type: type
Expand Down Expand Up @@ -473,9 +473,11 @@ RegExpCharacters = chars:( [^\\/] / RegExpEscaped )+ { return chars.join(""); }

RegExpEscaped = "\\" char_:. { return "\\" + char_; }

StringLiteral "string"
StringLiteral "string" = s:String { return ast.string(s); }

String
= parts:('"' DoubleStringCharacters '"' / "'" SingleStringCharacters "'") {
return ast.string(parts[1]);
return parts[1];
}

DoubleStringCharacters
Expand Down Expand Up @@ -536,7 +538,7 @@ UnicodeEscapeSequence
return String.fromCharCode(parseInt(digits, 16));
}

Identifier "identifier" = start:[a-zA-Z_$] rest:[a-zA-Z0-9_]* {
Identifier "identifier" = start:[a-zA-Z_$] rest:[a-zA-Z_$0-9]* {
return start + rest.join("");
}

Expand Down
9 changes: 9 additions & 0 deletions src/test/generator-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,11 @@ suite("Rules Generator Tests", function() {
expect: {'.validate': "newData.hasChildren()",
'$key': {'.validate': "newData.isNumber()"}} },

{ data: "type T { 'a b': Number }",
expect: {'.validate': "newData.hasChildren(['a b'])",
'a b': {'.validate': "newData.isNumber()"},
'$other': {'.validate': 'false'}} },

{ data: "type T {a: Number, b: String}",
expect: {'.validate': "newData.hasChildren(['a', 'b'])",
a: {'.validate': "newData.isNumber()"},
Expand Down Expand Up @@ -393,6 +398,10 @@ suite("Rules Generator Tests", function() {
expect: /recursive/i },
{ data: "type X { $n: Number, $s: String } path / is X;",
expect: /wild property/ },
{ data: "type X { $$n: Number } path / is X;",
expect: /property names/i },
{ data: "type X { '\x01': Number } path / is X;",
expect: /property names/i },
{ data: "path / is Map;",
expect: /No type.*non-generic/ },
{ data: "type Pair<X, Y> {a: X, b: Y} path / is Pair;",
Expand Down
7 changes: 7 additions & 0 deletions src/test/parser-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,13 @@ suite("Rules Parser Tests", function() {
methods: {},
params: [],
}},

{ data: "type Foo { 'hyphen-prop': String }",
expect: { derivedFrom: ast.typeType('Object'),
properties: {"hyphen-prop": ast.typeType('String')},
methods: {},
params: [],
}},
];

helper.dataDrivenTest(tests, function(data, expect) {
Expand Down

0 comments on commit 4a8a54c

Please sign in to comment.