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 94a22c4
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 0 deletions.
72 changes: 72 additions & 0 deletions fluent-syntax/src/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,50 @@
*/
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 +62,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 +227,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 +241,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 94a22c4

Please sign in to comment.