Skip to content

Commit

Permalink
BaseNode.equals support, wip, needs more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Pike committed Mar 19, 2018
1 parent 8ed4e4b commit 0452a80
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 0 deletions.
73 changes: 73 additions & 0 deletions fluent-syntax/src/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,51 @@
*/
class BaseNode {
constructor() {}

equals(other, ignoredFields = ['span']) {
const thisKeys = new Set(Object.keys(this));
const otherKeys = new Set(Object.keys(other));
if (ignoredFields) {
for (const fieldName of ignoredFields) {
thisKeys.delete(fieldName);
otherKeys.delete(fieldName);
}
}
if (thisKeys.size !== otherKeys.size) {
return false;
}
for (const fieldName of thisKeys) {
if (!otherKeys.has(fieldName)) {
return false;
}
const thisVal = this[fieldName];
const otherVal = other[fieldName];
if (typeof thisVal !== typeof otherVal) {
return false;
}
if (thisVal instanceof Array) {
if (thisVal.length !== otherVal.length) {
return false;
}
// Sort elements of order-agnostic fields to ensure the
// comparison is order-agnostic as well. Annotations should be
// here too but they don't have sorting keys.
if (['attributes', 'variants'].indexOf(fieldName) >= 0) {
thisVal.sort(sorting_key_compare);
otherVal.sort(sorting_key_compare);
}
for (let i=0, ii=thisVal.length; i<ii; ++i) {
if (!scalars_equal(thisVal[i], otherVal[i], ignoredFields)) {
return false;
}
}
}
else if (!scalars_equal(thisVal, otherVal, ignoredFields)) {
return false;
}
}
return true;
}
}

/*
Expand All @@ -18,6 +63,23 @@ class SyntaxNode extends BaseNode {
}
}

function scalars_equal(thisVal, otherVal, ignoredFields) {
if (thisVal instanceof BaseNode) {
return thisVal.equals(otherVal, ignoredFields);
}
return thisVal === otherVal;
}

function sorting_key_compare(left, right) {
if (left.sorting_key < right.sorting_key) {
return -1;
}
if (left.sorting_key === right.sorting_key) {
return 0;
}
return 1;
}

export class Resource extends SyntaxNode {
constructor(body = []) {
super();
Expand Down Expand Up @@ -166,6 +228,10 @@ export class Attribute extends SyntaxNode {
this.id = id;
this.value = value;
}

get sorting_key() {
return this.id.name;
}
}

export class Variant extends SyntaxNode {
Expand All @@ -176,6 +242,13 @@ export class Variant extends SyntaxNode {
this.value = value;
this.default = def;
}

get sorting_key() {
if (this.key instanceof NumberExpression) {
return this.key.value;
}
return this.key.name;
}
}

export class NamedArgument extends SyntaxNode {
Expand Down
30 changes: 30 additions & 0 deletions fluent-syntax/test/ast_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict';

import assert from 'assert';
import * as AST from '../src/ast';

suite('BaseNode.equals', function() {
test('Identifier.equals', function() {
const thisNode = new AST.Identifier("name");
const otherNode = new AST.Identifier("name");
assert.strictEqual(thisNode.equals(otherNode), true);
});
test('Node.type', function() {
const thisNode = new AST.Identifier("name");
const otherNode = new AST.Function("name");
assert.strictEqual(thisNode.equals(otherNode), false);
});
test('Array children', function() {
const thisNode = new AST.Pattern([
new AST.TextElement("one"),
new AST.TextElement("two"),
new AST.TextElement("three"),
]);
let otherNode = new AST.Pattern([
new AST.TextElement("one"),
new AST.TextElement("two"),
new AST.TextElement("three"),
]);
assert.strictEqual(thisNode.equals(otherNode), true);
});
});

0 comments on commit 0452a80

Please sign in to comment.