From 96a440af3597e7c2c9ef259d17c5d2ef93fd9204 Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Wed, 7 Feb 2024 11:32:27 -0500 Subject: [PATCH] chore(web): add and apply eslint formatting --- lib/binding_web/.eslintrc.js | 22 ++ lib/binding_web/binding.js | 258 ++++++++++--------- lib/binding_web/check-artifacts-fresh.js | 24 +- lib/binding_web/imports.js | 8 +- lib/binding_web/package.json | 2 + lib/binding_web/suffix.js | 2 +- lib/binding_web/test/language-test.js | 56 ++--- lib/binding_web/test/node-test.js | 304 +++++++++++------------ lib/binding_web/test/parser-test.js | 149 +++++------ lib/binding_web/test/query-test.js | 232 ++++++++--------- lib/binding_web/test/tree-test.js | 134 +++++----- 11 files changed, 622 insertions(+), 569 deletions(-) create mode 100644 lib/binding_web/.eslintrc.js diff --git a/lib/binding_web/.eslintrc.js b/lib/binding_web/.eslintrc.js new file mode 100644 index 00000000..38709eb8 --- /dev/null +++ b/lib/binding_web/.eslintrc.js @@ -0,0 +1,22 @@ +module.exports = { + 'env': { + 'commonjs': true, + 'es2021': true, + }, + 'extends': 'google', + 'overrides': [ + ], + 'parserOptions': { + 'ecmaVersion': 'latest', + 'sourceType': 'module', + }, + 'rules': { + 'indent': ['error', 2, {'SwitchCase': 1}], + 'max-len': [ + 'error', + {'code': 120, 'ignoreComments': true, 'ignoreUrls': true, 'ignoreStrings': true, 'ignoreTemplateLiterals': true}, + ], + 'require-jsdoc': 0, + 'new-cap': 0, + }, +}; diff --git a/lib/binding_web/binding.js b/lib/binding_web/binding.js index ca45d459..817cc48d 100644 --- a/lib/binding_web/binding.js +++ b/lib/binding_web/binding.js @@ -13,12 +13,14 @@ const PREDICATE_STEP_TYPE_STRING = 2; const LANGUAGE_FUNCTION_REGEX = /^_?tree_sitter_\w+/; -var VERSION; -var MIN_COMPATIBLE_VERSION; -var TRANSFER_BUFFER; -var currentParseCallback; -var currentLogCallback; +let VERSION; +let MIN_COMPATIBLE_VERSION; +let TRANSFER_BUFFER; +let currentParseCallback; +// eslint-disable-next-line no-unused-vars +let currentLogCallback; +// eslint-disable-next-line no-unused-vars class ParserImpl { static init() { TRANSFER_BUFFER = C._ts_init(); @@ -50,7 +52,7 @@ class ParserImpl { if (version < MIN_COMPATIBLE_VERSION || VERSION < version) { throw new Error( `Incompatible language version ${version}. ` + - `Compatibility range ${MIN_COMPATIBLE_VERSION} through ${VERSION}.` + `Compatibility range ${MIN_COMPATIBLE_VERSION} through ${VERSION}.`, ); } } else { @@ -62,7 +64,7 @@ class ParserImpl { } getLanguage() { - return this.language + return this.language; } parse(callback, oldTree, options) { @@ -71,7 +73,7 @@ class ParserImpl { } else if (typeof callback === 'function') { currentParseCallback = callback; } else { - throw new Error("Argument must be a string or a function"); + throw new Error('Argument must be a string or a function'); } if (this.logCallback) { @@ -99,7 +101,7 @@ class ParserImpl { this[1], oldTree ? oldTree[0] : 0, rangeAddress, - rangeCount + rangeCount, ); if (!treeAddress) { @@ -129,8 +131,8 @@ class ParserImpl { setLogger(callback) { if (!callback) { callback = null; - } else if (typeof callback !== "function") { - throw new Error("Logger callback must be a function"); + } else if (typeof callback !== 'function') { + throw new Error('Logger callback must be a function'); } this.logCallback = callback; return this; @@ -403,7 +405,7 @@ class Node { startPosition.row, startPosition.column, endPosition.row, - endPosition.column + endPosition.column, ); // Instantiate the nodes based on the data returned. @@ -460,7 +462,7 @@ class Node { } marshalNode(this); - let address = TRANSFER_BUFFER + SIZE_OF_NODE; + const address = TRANSFER_BUFFER + SIZE_OF_NODE; setValue(address, start, 'i32'); setValue(address + SIZE_OF_INT, end, 'i32'); C._ts_node_descendant_for_index_wasm(this.tree[0]); @@ -473,7 +475,7 @@ class Node { } marshalNode(this); - let address = TRANSFER_BUFFER + SIZE_OF_NODE; + const address = TRANSFER_BUFFER + SIZE_OF_NODE; setValue(address, start, 'i32'); setValue(address + SIZE_OF_INT, end, 'i32'); C._ts_node_named_descendant_for_index_wasm(this.tree[0]); @@ -486,7 +488,7 @@ class Node { } marshalNode(this); - let address = TRANSFER_BUFFER + SIZE_OF_NODE; + const address = TRANSFER_BUFFER + SIZE_OF_NODE; marshalPoint(address, start); marshalPoint(address + SIZE_OF_POINT, end); C._ts_node_descendant_for_position_wasm(this.tree[0]); @@ -499,7 +501,7 @@ class Node { } marshalNode(this); - let address = TRANSFER_BUFFER + SIZE_OF_NODE; + const address = TRANSFER_BUFFER + SIZE_OF_NODE; marshalPoint(address, start); marshalPoint(address + SIZE_OF_POINT, end); C._ts_node_named_descendant_for_position_wasm(this.tree[0]); @@ -747,7 +749,7 @@ class Language { sourceAddress, sourceLength, TRANSFER_BUFFER, - TRANSFER_BUFFER + SIZE_OF_INT + TRANSFER_BUFFER + SIZE_OF_INT, ); if (!address) { @@ -769,11 +771,11 @@ class Language { break; case 5: error = new TypeError(`Bad pattern structure at offset ${errorIndex}: '${suffix}'...`); - word = ""; + word = ''; break; default: error = new SyntaxError(`Bad syntax at offset ${errorIndex}: '${suffix}'...`); - word = ""; + word = ''; break; } error.index = errorIndex; @@ -792,7 +794,7 @@ class Language { const nameAddress = C._ts_query_capture_name_for_id( address, i, - TRANSFER_BUFFER + TRANSFER_BUFFER, ); const nameLength = getValue(TRANSFER_BUFFER, 'i32'); captureNames[i] = UTF8ToString(nameAddress, nameLength); @@ -802,7 +804,7 @@ class Language { const valueAddress = C._ts_query_string_value_for_id( address, i, - TRANSFER_BUFFER + TRANSFER_BUFFER, ); const nameLength = getValue(TRANSFER_BUFFER, 'i32'); stringValues[i] = UTF8ToString(valueAddress, nameLength); @@ -817,7 +819,7 @@ class Language { const predicatesAddress = C._ts_query_predicates_for_pattern( address, i, - TRANSFER_BUFFER + TRANSFER_BUFFER, ); const stepCount = getValue(TRANSFER_BUFFER, 'i32'); @@ -849,103 +851,121 @@ class Language { isPositive = false; case 'any-eq?': case 'eq?': - if (steps.length !== 3) throw new Error( - `Wrong number of arguments to \`#${operator}\` predicate. Expected 2, got ${steps.length - 1}` - ); - if (steps[1].type !== 'capture') throw new Error( - `First argument of \`#${operator}\` predicate must be a capture. Got "${steps[1].value}"` - ); + if (steps.length !== 3) { + throw new Error( + `Wrong number of arguments to \`#${operator}\` predicate. Expected 2, got ${steps.length - 1}`, + ); + } + if (steps[1].type !== 'capture') { + throw new Error( + `First argument of \`#${operator}\` predicate must be a capture. Got "${steps[1].value}"`, + ); + } matchAll = !operator.startsWith('any-'); if (steps[2].type === 'capture') { const captureName1 = steps[1].name; const captureName2 = steps[2].name; - textPredicates[i].push(function (captures) { - let nodes_1 = []; - let nodes_2 = []; + textPredicates[i].push(function(captures) { + const nodes1 = []; + const nodes2 = []; for (const c of captures) { - if (c.name === captureName1) nodes_1.push(c.node); - if (c.name === captureName2) nodes_2.push(c.node); + if (c.name === captureName1) nodes1.push(c.node); + if (c.name === captureName2) nodes2.push(c.node); } - let compare = (n1, n2, positive) => { + const compare = (n1, n2, positive) => { return positive ? n1.text === n2.text : n1.text !== n2.text; }; - return matchAll - ? nodes_1.every(n1 => nodes_2.some(n2 => compare(n1, n2, isPositive))) - : nodes_1.some(n1 => nodes_2.some(n2 => compare(n1, n2, isPositive))); + return matchAll ? + nodes1.every((n1) => nodes2.some((n2) => compare(n1, n2, isPositive))) : + nodes1.some((n1) => nodes2.some((n2) => compare(n1, n2, isPositive))); }); } else { captureName = steps[1].name; const stringValue = steps[2].value; - let matches = (n) => n.text === stringValue; - let doesNotMatch = (n) => n.text !== stringValue; - textPredicates[i].push(function (captures) { - let nodes = []; + const matches = (n) => n.text === stringValue; + const doesNotMatch = (n) => n.text !== stringValue; + textPredicates[i].push(function(captures) { + const nodes = []; for (const c of captures) { if (c.name === captureName) nodes.push(c.node); } - let test = isPositive ? matches : doesNotMatch; - return matchAll - ? nodes.every(test) - : nodes.some(test); + const test = isPositive ? matches : doesNotMatch; + return matchAll ? + nodes.every(test) : + nodes.some(test); }); } break; - case "any-not-match?": - case "not-match?": - isPositive = false; - case "any-match?": - case "match?": - if (steps.length !== 3) throw new Error( - `Wrong number of arguments to \`#${operator}\` predicate. Expected 2, got ${steps.length - 1}.` - ); - if (steps[1].type !== 'capture') throw new Error( - `First argument of \`#${operator}\` predicate must be a capture. Got "${steps[1].value}".` - ); - if (steps[2].type !== 'string') throw new Error( - `Second argument of \`#${operator}\` predicate must be a string. Got @${steps[2].value}.` - ); + case 'any-not-match?': + case 'not-match?': + isPositive = false; + case 'any-match?': + case 'match?': + if (steps.length !== 3) { + throw new Error( + `Wrong number of arguments to \`#${operator}\` predicate. Expected 2, got ${steps.length - 1}.`, + ); + } + if (steps[1].type !== 'capture') { + throw new Error( + `First argument of \`#${operator}\` predicate must be a capture. Got "${steps[1].value}".`, + ); + } + if (steps[2].type !== 'string') { + throw new Error( + `Second argument of \`#${operator}\` predicate must be a string. Got @${steps[2].value}.`, + ); + } captureName = steps[1].name; const regex = new RegExp(steps[2].value); matchAll = !operator.startsWith('any-'); - textPredicates[i].push(function (captures) { + textPredicates[i].push(function(captures) { const nodes = []; for (const c of captures) { if (c.name === captureName) nodes.push(c.node.text); } - let test = (text, positive) => { + const test = (text, positive) => { return positive ? regex.test(text) : !regex.test(text); }; if (nodes.length === 0) return !isPositive; - return matchAll - ? nodes.every(text => test(text, isPositive)) - : nodes.some(text => test(text, isPositive)) + return matchAll ? + nodes.every((text) => test(text, isPositive)) : + nodes.some((text) => test(text, isPositive)); }); break; case 'set!': - if (steps.length < 2 || steps.length > 3) throw new Error( - `Wrong number of arguments to \`#set!\` predicate. Expected 1 or 2. Got ${steps.length - 1}.` - ); - if (steps.some(s => s.type !== 'string')) throw new Error( - `Arguments to \`#set!\` predicate must be a strings.".` - ); + if (steps.length < 2 || steps.length > 3) { + throw new Error( + `Wrong number of arguments to \`#set!\` predicate. Expected 1 or 2. Got ${steps.length - 1}.`, + ); + } + if (steps.some((s) => s.type !== 'string')) { + throw new Error( + `Arguments to \`#set!\` predicate must be a strings.".`, + ); + } if (!setProperties[i]) setProperties[i] = {}; setProperties[i][steps[1].value] = steps[2] ? steps[2].value : null; break; case 'is?': case 'is-not?': - if (steps.length < 2 || steps.length > 3) throw new Error( - `Wrong number of arguments to \`#${operator}\` predicate. Expected 1 or 2. Got ${steps.length - 1}.` - ); - if (steps.some(s => s.type !== 'string')) throw new Error( - `Arguments to \`#${operator}\` predicate must be a strings.".` - ); + if (steps.length < 2 || steps.length > 3) { + throw new Error( + `Wrong number of arguments to \`#${operator}\` predicate. Expected 1 or 2. Got ${steps.length - 1}.`, + ); + } + if (steps.some((s) => s.type !== 'string')) { + throw new Error( + `Arguments to \`#${operator}\` predicate must be a strings.".`, + ); + } const properties = operator === 'is?' ? assertedProperties : refutedProperties; if (!properties[i]) properties[i] = {}; properties[i][steps[1].value] = steps[2] ? steps[2].value : null; @@ -954,26 +974,32 @@ class Language { case 'not-any-of?': isPositive = false; case 'any-of?': - if (steps.length < 2) throw new Error( - `Wrong number of arguments to \`#${operator}\` predicate. Expected at least 1. Got ${steps.length - 1}.` - ); - if (steps[1].type !== 'capture') throw new Error( - `First argument of \`#${operator}\` predicate must be a capture. Got "${steps[1].value}".` - ); - for (let i = 2; i < steps.length; i++) { - if (steps[i].type !== 'string') throw new Error( - `Arguments to \`#${operator}\` predicate must be a strings.".` + if (steps.length < 2) { + throw new Error( + `Wrong number of arguments to \`#${operator}\` predicate. Expected at least 1. Got ${steps.length - 1}.`, ); } + if (steps[1].type !== 'capture') { + throw new Error( + `First argument of \`#${operator}\` predicate must be a capture. Got "${steps[1].value}".`, + ); + } + for (let i = 2; i < steps.length; i++) { + if (steps[i].type !== 'string') { + throw new Error( + `Arguments to \`#${operator}\` predicate must be a strings.".`, + ); + } + } captureName = steps[1].name; - const values = steps.slice(2).map(s => s.value); - textPredicates[i].push(function (captures) { + const values = steps.slice(2).map((s) => s.value); + textPredicates[i].push(function(captures) { const nodes = []; for (const c of captures) { if (c.name === captureName) nodes.push(c.node.text); } if (nodes.length === 0) return !isPositive; - return nodes.every(text => values.includes(text)) === isPositive; + return nodes.every((text) => values.includes(text)) === isPositive; }); break; @@ -999,7 +1025,7 @@ class Language { predicates, Object.freeze(setProperties), Object.freeze(assertedProperties), - Object.freeze(refutedProperties) + Object.freeze(refutedProperties), ); } @@ -1018,28 +1044,28 @@ class Language { bytes = Promise.resolve(fs.readFileSync(url)); } else { bytes = fetch(url) - .then(response => response.arrayBuffer() - .then(buffer => { + .then((response) => response.arrayBuffer() + .then((buffer) => { if (response.ok) { return new Uint8Array(buffer); } else { const body = new TextDecoder('utf-8').decode(buffer); - throw new Error(`Language.load failed with status ${response.status}.\n\n${body}`) + throw new Error(`Language.load failed with status ${response.status}.\n\n${body}`); } })); } } return bytes - .then(bytes => loadWebAssemblyModule(bytes, {loadAsync: true})) - .then(mod => { - const symbolNames = Object.keys(mod) - const functionName = symbolNames.find(key => + .then((bytes) => loadWebAssemblyModule(bytes, {loadAsync: true})) + .then((mod) => { + const symbolNames = Object.keys(mod); + const functionName = symbolNames.find((key) => LANGUAGE_FUNCTION_REGEX.test(key) && - !key.includes("external_scanner_") + !key.includes('external_scanner_'), ); if (!functionName) { - console.log(`Couldn't find language function in WASM file. Symbols:\n${JSON.stringify(symbolNames, null, 2)}`) + console.log(`Couldn't find language function in WASM file. Symbols:\n${JSON.stringify(symbolNames, null, 2)}`); } const languageAddress = mod[functionName](); return new Language(INTERNAL, languageAddress); @@ -1059,7 +1085,7 @@ class LookaheadIterable { } get currentType() { - return this.language.types[this.currentTypeId] || 'ERROR' + return this.language.types[this.currentTypeId] || 'ERROR'; } delete() { @@ -1085,11 +1111,11 @@ class LookaheadIterable { return { next() { if (C._ts_lookahead_iterator_next(self[0])) { - return { done: false, value: self.currentType }; + return {done: false, value: self.currentType}; } - return { done: true, value: "" }; - } + return {done: true, value: ''}; + }, }; } } @@ -1097,7 +1123,7 @@ class LookaheadIterable { class Query { constructor( internal, address, captureNames, textPredicates, predicates, - setProperties, assertedProperties, refutedProperties + setProperties, assertedProperties, refutedProperties, ) { assertInternal(internal); this[0] = address; @@ -1136,7 +1162,7 @@ class Query { startPosition.column, endPosition.row, endPosition.column, - matchLimit + matchLimit, ); const rawCount = getValue(TRANSFER_BUFFER, 'i32'); @@ -1155,7 +1181,7 @@ class Query { const captures = new Array(captureCount); address = unmarshalCaptures(this, node.tree, address, captures); - if (this.textPredicates[pattern].every(p => p(captures))) { + if (this.textPredicates[pattern].every((p) => p(captures))) { result[filteredCount++] = {pattern, captures}; const setProperties = this.setProperties[pattern]; if (setProperties) result[i].setProperties = setProperties; @@ -1192,7 +1218,7 @@ class Query { startPosition.column, endPosition.row, endPosition.column, - matchLimit + matchLimit, ); const count = getValue(TRANSFER_BUFFER, 'i32'); @@ -1211,10 +1237,10 @@ class Query { const captureIndex = getValue(address, 'i32'); address += SIZE_OF_INT; - captures.length = captureCount + captures.length = captureCount; address = unmarshalCaptures(this, node.tree, address, captures); - if (this.textPredicates[pattern].every(p => p(captures))) { + if (this.textPredicates[pattern].every((p) => p(captures))) { const capture = captures[captureIndex]; const setProperties = this.setProperties[pattern]; if (setProperties) capture.setProperties = setProperties; @@ -1231,7 +1257,7 @@ class Query { } predicatesForPattern(patternIndex) { - return this.predicates[patternIndex] + return this.predicates[patternIndex]; } didExceedMatchLimit() { @@ -1270,7 +1296,7 @@ function unmarshalCaptures(query, tree, address, result) { } function assertInternal(x) { - if (x !== INTERNAL) throw new Error('Illegal constructor') + if (x !== INTERNAL) throw new Error('Illegal constructor'); } function isPoint(point) { @@ -1319,25 +1345,25 @@ function unmarshalNode(tree, address = TRANSFER_BUFFER) { function marshalTreeCursor(cursor, address = TRANSFER_BUFFER) { setValue(address + 0 * SIZE_OF_INT, cursor[0], 'i32'), setValue(address + 1 * SIZE_OF_INT, cursor[1], 'i32'), - setValue(address + 2 * SIZE_OF_INT, cursor[2], 'i32') + setValue(address + 2 * SIZE_OF_INT, cursor[2], 'i32'); } function unmarshalTreeCursor(cursor) { cursor[0] = getValue(TRANSFER_BUFFER + 0 * SIZE_OF_INT, 'i32'), cursor[1] = getValue(TRANSFER_BUFFER + 1 * SIZE_OF_INT, 'i32'), - cursor[2] = getValue(TRANSFER_BUFFER + 2 * SIZE_OF_INT, 'i32') + cursor[2] = getValue(TRANSFER_BUFFER + 2 * SIZE_OF_INT, 'i32'); } function marshalPoint(address, point) { - setValue(address, point.row, 'i32') - setValue(address + SIZE_OF_INT, point.column, 'i32') + setValue(address, point.row, 'i32'); + setValue(address + SIZE_OF_INT, point.column, 'i32'); } function unmarshalPoint(address) { return { row: getValue(address, 'i32'), - column: getValue(address + SIZE_OF_INT, 'i32') - } + column: getValue(address + SIZE_OF_INT, 'i32'), + }; } function marshalRange(address, range) { diff --git a/lib/binding_web/check-artifacts-fresh.js b/lib/binding_web/check-artifacts-fresh.js index 8cac6ba2..a0c24933 100755 --- a/lib/binding_web/check-artifacts-fresh.js +++ b/lib/binding_web/check-artifacts-fresh.js @@ -1,19 +1,19 @@ #!/usr/bin/env node -const fs = require("fs"); -const path = require("path"); +const fs = require('fs'); +const path = require('path'); const inputFiles = [ - "binding.c", - "binding.js", - "exports.txt", - "imports.js", - "prefix.js", - ...list("../include/tree_sitter"), - ...list("../src"), + 'binding.c', + 'binding.js', + 'exports.txt', + 'imports.js', + 'prefix.js', + ...list('../include/tree_sitter'), + ...list('../src'), ]; -const outputFiles = ["tree-sitter.js", "tree-sitter.wasm"]; +const outputFiles = ['tree-sitter.js', 'tree-sitter.wasm']; const outputMtime = Math.min(...outputFiles.map(mtime)); @@ -26,8 +26,8 @@ for (const inputFile of inputFiles) { function list(dir) { return fs - .readdirSync(path.join(__dirname, dir), "utf8") - .filter((p) => !p.startsWith(".")) + .readdirSync(path.join(__dirname, dir), 'utf8') + .filter((p) => !p.startsWith('.')) .map((p) => path.join(dir, p)); } diff --git a/lib/binding_web/imports.js b/lib/binding_web/imports.js index a76c42ac..b0d1d9f5 100644 --- a/lib/binding_web/imports.js +++ b/lib/binding_web/imports.js @@ -4,10 +4,10 @@ mergeInto(LibraryManager.library, { index, row, column, - lengthAddress + lengthAddress, ) { - var INPUT_BUFFER_SIZE = 10 * 1024; - var string = currentParseCallback(index, {row: row, column: column}); + const INPUT_BUFFER_SIZE = 10 * 1024; + const string = currentParseCallback(index, {row: row, column: column}); if (typeof string === 'string') { setValue(lengthAddress, string.length, 'i32'); stringToUTF16(string, inputBufferAddress, INPUT_BUFFER_SIZE); @@ -21,5 +21,5 @@ mergeInto(LibraryManager.library, { const message = UTF8ToString(messageAddress); currentLogCallback(message, isLexMessage !== 0); } - } + }, }); diff --git a/lib/binding_web/package.json b/lib/binding_web/package.json index 47429fd2..3d484eb8 100644 --- a/lib/binding_web/package.json +++ b/lib/binding_web/package.json @@ -28,6 +28,8 @@ "homepage": "https://github.com/tree-sitter/tree-sitter/tree/master/lib/binding_web", "devDependencies": { "chai": "^4.3.7", + "eslint": ">=8.56.0", + "eslint-config-google": "^0.14.0", "mocha": "^10.2.0", "terser": "^5.16.6" } diff --git a/lib/binding_web/suffix.js b/lib/binding_web/suffix.js index cd91f919..8e096f61 100644 --- a/lib/binding_web/suffix.js +++ b/lib/binding_web/suffix.js @@ -20,4 +20,4 @@ if (typeof exports === 'object') { module.exports = TreeSitter; -} \ No newline at end of file +} diff --git a/lib/binding_web/test/language-test.js b/lib/binding_web/test/language-test.js index 467b56c5..70e59257 100644 --- a/lib/binding_web/test/language-test.js +++ b/lib/binding_web/test/language-test.js @@ -1,56 +1,56 @@ -const { assert } = require("chai"); +const {assert} = require('chai'); let JavaScript; -describe("Language", () => { - before(async () => ({ JavaScript } = await require("./helper"))); +describe('Language', () => { + before(async () => ({JavaScript} = await require('./helper'))); - describe(".fieldIdForName, .fieldNameForId", () => { - it("converts between the string and integer representations of fields", () => { - const nameId = JavaScript.fieldIdForName("name"); - const bodyId = JavaScript.fieldIdForName("body"); + describe('.fieldIdForName, .fieldNameForId', () => { + it('converts between the string and integer representations of fields', () => { + const nameId = JavaScript.fieldIdForName('name'); + const bodyId = JavaScript.fieldIdForName('body'); assert.isBelow(nameId, JavaScript.fieldCount); assert.isBelow(bodyId, JavaScript.fieldCount); - assert.equal("name", JavaScript.fieldNameForId(nameId)); - assert.equal("body", JavaScript.fieldNameForId(bodyId)); + assert.equal('name', JavaScript.fieldNameForId(nameId)); + assert.equal('body', JavaScript.fieldNameForId(bodyId)); }); - it("handles invalid inputs", () => { - assert.equal(null, JavaScript.fieldIdForName("namezzz")); + it('handles invalid inputs', () => { + assert.equal(null, JavaScript.fieldIdForName('namezzz')); assert.equal(null, JavaScript.fieldNameForId(-1)); assert.equal(null, JavaScript.fieldNameForId(10000)); }); }); - describe(".idForNodeType, .nodeTypeForId, .nodeTypeIsNamed", () => { - it("converts between the string and integer representations of a node type", () => { - const exportStatementId = JavaScript.idForNodeType("export_statement", true); - const starId = JavaScript.idForNodeType("*", false); + describe('.idForNodeType, .nodeTypeForId, .nodeTypeIsNamed', () => { + it('converts between the string and integer representations of a node type', () => { + const exportStatementId = JavaScript.idForNodeType('export_statement', true); + const starId = JavaScript.idForNodeType('*', false); assert.isBelow(exportStatementId, JavaScript.nodeTypeCount); assert.isBelow(starId, JavaScript.nodeTypeCount); - assert.equal(true, JavaScript.nodeTypeIsNamed(exportStatementId)) - assert.equal("export_statement", JavaScript.nodeTypeForId(exportStatementId)) - assert.equal(false, JavaScript.nodeTypeIsNamed(starId)) - assert.equal("*", JavaScript.nodeTypeForId(starId)) + assert.equal(true, JavaScript.nodeTypeIsNamed(exportStatementId)); + assert.equal('export_statement', JavaScript.nodeTypeForId(exportStatementId)); + assert.equal(false, JavaScript.nodeTypeIsNamed(starId)); + assert.equal('*', JavaScript.nodeTypeForId(starId)); }); - it("handles invalid inputs", () => { + it('handles invalid inputs', () => { assert.equal(null, JavaScript.nodeTypeForId(-1)); assert.equal(null, JavaScript.nodeTypeForId(10000)); - assert.equal(null, JavaScript.idForNodeType("export_statement", false)); + assert.equal(null, JavaScript.idForNodeType('export_statement', false)); }); }); }); -describe("Lookahead iterator", () => { +describe('Lookahead iterator', () => { let lookahead; let state; before(async () => { let Parser; - ({ JavaScript, Parser } = await require("./helper")); + ({JavaScript, Parser} = await require('./helper')); const parser = new Parser().setLanguage(JavaScript); - const tree = parser.parse("function fn() {}"); + const tree = parser.parse('function fn() {}'); parser.delete(); const cursor = tree.walk(); assert(cursor.gotoFirstChild()); @@ -64,21 +64,21 @@ describe("Lookahead iterator", () => { lookahead.delete(); }); - const expected = ["identifier", "comment", "html_comment", "(", "*", "formal_parameters", "ERROR"]; - it("should iterate over valid symbols in the state", () => { + const expected = ['identifier', 'comment', 'html_comment', '(', '*', 'formal_parameters', 'ERROR']; + it('should iterate over valid symbols in the state', () => { const symbols = Array.from(lookahead); assert.includeMembers(symbols, expected); assert.lengthOf(symbols, expected.length); }); - it("should reset to the initial state", () => { + it('should reset to the initial state', () => { assert(lookahead.resetState(state)); const symbols = Array.from(lookahead); assert.includeMembers(symbols, expected); assert.lengthOf(symbols, expected.length); }); - it("should reset", () => { + it('should reset', () => { assert(lookahead.reset(JavaScript, state)); const symbols = Array.from(lookahead); assert.includeMembers(symbols, expected); diff --git a/lib/binding_web/test/node-test.js b/lib/binding_web/test/node-test.js index a1011154..9d59de7f 100644 --- a/lib/binding_web/test/node-test.js +++ b/lib/binding_web/test/node-test.js @@ -1,11 +1,11 @@ const {assert} = require('chai'); -let Parser, JavaScript; +let Parser; let JavaScript; -describe("Node", () => { - let parser, tree; +describe('Node', () => { + let parser; let tree; before(async () => - ({Parser, JavaScript} = await require('./helper')) + ({Parser, JavaScript} = await require('./helper')), ); beforeEach(() => { @@ -18,83 +18,83 @@ describe("Node", () => { tree.delete(); }); - describe(".children", () => { - it("returns an array of child nodes", () => { - tree = parser.parse("x10 + 1000"); + describe('.children', () => { + it('returns an array of child nodes', () => { + tree = parser.parse('x10 + 1000'); assert.equal(1, tree.rootNode.children.length); const sumNode = tree.rootNode.firstChild.firstChild; assert.deepEqual( - sumNode.children.map(child => child.type), - ["identifier", "+", "number"] + sumNode.children.map((child) => child.type), + ['identifier', '+', 'number'], ); }); }); - describe(".namedChildren", () => { - it("returns an array of named child nodes", () => { - tree = parser.parse("x10 + 1000"); + describe('.namedChildren', () => { + it('returns an array of named child nodes', () => { + tree = parser.parse('x10 + 1000'); const sumNode = tree.rootNode.firstChild.firstChild; assert.equal(1, tree.rootNode.namedChildren.length); assert.deepEqual( - ["identifier", "number"], - sumNode.namedChildren.map(child => child.type) + ['identifier', 'number'], + sumNode.namedChildren.map((child) => child.type), ); }); }); - describe(".startIndex and .endIndex", () => { - it("returns the character index where the node starts/ends in the text", () => { - tree = parser.parse("a👍👎1 / b👎c👎"); + describe('.startIndex and .endIndex', () => { + it('returns the character index where the node starts/ends in the text', () => { + tree = parser.parse('a👍👎1 / b👎c👎'); const quotientNode = tree.rootNode.firstChild.firstChild; assert.equal(0, quotientNode.startIndex); assert.equal(15, quotientNode.endIndex); assert.deepEqual( [0, 7, 9], - quotientNode.children.map(child => child.startIndex) + quotientNode.children.map((child) => child.startIndex), ); assert.deepEqual( [6, 8, 15], - quotientNode.children.map(child => child.endIndex) + quotientNode.children.map((child) => child.endIndex), ); }); }); - describe(".startPosition and .endPosition", () => { - it("returns the row and column where the node starts/ends in the text", () => { - tree = parser.parse("x10 + 1000"); + describe('.startPosition and .endPosition', () => { + it('returns the row and column where the node starts/ends in the text', () => { + tree = parser.parse('x10 + 1000'); const sumNode = tree.rootNode.firstChild.firstChild; - assert.equal("binary_expression", sumNode.type); + assert.equal('binary_expression', sumNode.type); - assert.deepEqual({ row: 0, column: 0 }, sumNode.startPosition); - assert.deepEqual({ row: 0, column: 10 }, sumNode.endPosition); + assert.deepEqual({row: 0, column: 0}, sumNode.startPosition); + assert.deepEqual({row: 0, column: 10}, sumNode.endPosition); assert.deepEqual( - [{ row: 0, column: 0 }, { row: 0, column: 4 }, { row: 0, column: 6 }], - sumNode.children.map(child => child.startPosition) + [{row: 0, column: 0}, {row: 0, column: 4}, {row: 0, column: 6}], + sumNode.children.map((child) => child.startPosition), ); assert.deepEqual( - [{ row: 0, column: 3 }, { row: 0, column: 5 }, { row: 0, column: 10 }], - sumNode.children.map(child => child.endPosition) + [{row: 0, column: 3}, {row: 0, column: 5}, {row: 0, column: 10}], + sumNode.children.map((child) => child.endPosition), ); }); - it("handles characters that occupy two UTF16 code units", () => { - tree = parser.parse("a👍👎1 /\n b👎c👎"); + it('handles characters that occupy two UTF16 code units', () => { + tree = parser.parse('a👍👎1 /\n b👎c👎'); const sumNode = tree.rootNode.firstChild.firstChild; assert.deepEqual( [ - [{ row: 0, column: 0 }, { row: 0, column: 6 }], - [{ row: 0, column: 7 }, { row: 0, column: 8 }], - [{ row: 1, column: 1 }, { row: 1, column: 7 }] + [{row: 0, column: 0}, {row: 0, column: 6}], + [{row: 0, column: 7}, {row: 0, column: 8}], + [{row: 1, column: 1}, {row: 1, column: 7}], ], - sumNode.children.map(child => [child.startPosition, child.endPosition]) + sumNode.children.map((child) => [child.startPosition, child.endPosition]), ); }); }); - describe(".parent", () => { - it("returns the node's parent", () => { - tree = parser.parse("x10 + 1000"); + describe('.parent', () => { + it('returns the node\'s parent', () => { + tree = parser.parse('x10 + 1000'); const sumNode = tree.rootNode.firstChild; const variableNode = sumNode.firstChild; assert.notEqual(sumNode.id, variableNode.id); @@ -105,7 +105,7 @@ describe("Node", () => { describe('.child(), .firstChild, .lastChild', () => { it('returns null when the node has no children', () => { - tree = parser.parse("x10 + 1000"); + tree = parser.parse('x10 + 1000'); const sumNode = tree.rootNode.firstChild.firstChild; const variableNode = sumNode.firstChild; assert.equal(variableNode.firstChild, null); @@ -113,12 +113,12 @@ describe("Node", () => { assert.equal(variableNode.firstNamedChild, null); assert.equal(variableNode.lastNamedChild, null); assert.equal(variableNode.child(1), null); - }) + }); }); describe('.childForFieldName()', () => { it('returns null when the node has no children', () => { - tree = parser.parse("class A { b() {} }"); + tree = parser.parse('class A { b() {} }'); const classNode = tree.rootNode.firstChild; assert.equal(classNode.type, 'class_declaration'); @@ -145,119 +145,119 @@ describe("Node", () => { }); }); - describe(".nextSibling and .previousSibling", () => { - it("returns the node's next and previous sibling", () => { - tree = parser.parse("x10 + 1000"); + describe('.nextSibling and .previousSibling', () => { + it('returns the node\'s next and previous sibling', () => { + tree = parser.parse('x10 + 1000'); const sumNode = tree.rootNode.firstChild.firstChild; assert.equal(sumNode.children[1].id, sumNode.children[0].nextSibling.id); assert.equal(sumNode.children[2].id, sumNode.children[1].nextSibling.id); assert.equal( sumNode.children[0].id, - sumNode.children[1].previousSibling.id + sumNode.children[1].previousSibling.id, ); assert.equal( sumNode.children[1].id, - sumNode.children[2].previousSibling.id + sumNode.children[2].previousSibling.id, ); }); }); - describe(".nextNamedSibling and .previousNamedSibling", () => { - it("returns the node's next and previous named sibling", () => { - tree = parser.parse("x10 + 1000"); + describe('.nextNamedSibling and .previousNamedSibling', () => { + it('returns the node\'s next and previous named sibling', () => { + tree = parser.parse('x10 + 1000'); const sumNode = tree.rootNode.firstChild.firstChild; assert.equal( sumNode.namedChildren[1].id, - sumNode.namedChildren[0].nextNamedSibling.id + sumNode.namedChildren[0].nextNamedSibling.id, ); assert.equal( sumNode.namedChildren[0].id, - sumNode.namedChildren[1].previousNamedSibling.id + sumNode.namedChildren[1].previousNamedSibling.id, ); }); }); - describe(".descendantForIndex(min, max)", () => { - it("returns the smallest node that spans the given range", () => { - tree = parser.parse("x10 + 1000"); + describe('.descendantForIndex(min, max)', () => { + it('returns the smallest node that spans the given range', () => { + tree = parser.parse('x10 + 1000'); const sumNode = tree.rootNode.firstChild.firstChild; - assert.equal("identifier", sumNode.descendantForIndex(1, 2).type); - assert.equal("+", sumNode.descendantForIndex(4, 4).type); + assert.equal('identifier', sumNode.descendantForIndex(1, 2).type); + assert.equal('+', sumNode.descendantForIndex(4, 4).type); assert.throws(() => { sumNode.descendantForIndex(1, {}); - }, "Arguments must be numbers"); + }, 'Arguments must be numbers'); assert.throws(() => { sumNode.descendantForIndex(); - }, "Arguments must be numbers"); + }, 'Arguments must be numbers'); }); }); - describe(".namedDescendantForIndex", () => { - it("returns the smallest node that spans the given range", () => { - tree = parser.parse("x10 + 1000"); + describe('.namedDescendantForIndex', () => { + it('returns the smallest node that spans the given range', () => { + tree = parser.parse('x10 + 1000'); const sumNode = tree.rootNode.firstChild; - assert.equal("identifier", sumNode.descendantForIndex(1, 2).type); - assert.equal("+", sumNode.descendantForIndex(4, 4).type); + assert.equal('identifier', sumNode.descendantForIndex(1, 2).type); + assert.equal('+', sumNode.descendantForIndex(4, 4).type); }); }); - describe(".descendantForPosition(min, max)", () => { - it("returns the smallest node that spans the given range", () => { - tree = parser.parse("x10 + 1000"); + describe('.descendantForPosition(min, max)', () => { + it('returns the smallest node that spans the given range', () => { + tree = parser.parse('x10 + 1000'); const sumNode = tree.rootNode.firstChild; assert.equal( - "identifier", + 'identifier', sumNode.descendantForPosition( - { row: 0, column: 1 }, - { row: 0, column: 2 } - ).type + {row: 0, column: 1}, + {row: 0, column: 2}, + ).type, ); assert.equal( - "+", - sumNode.descendantForPosition({ row: 0, column: 4 }).type + '+', + sumNode.descendantForPosition({row: 0, column: 4}).type, ); assert.throws(() => { sumNode.descendantForPosition(1, {}); - }, "Arguments must be {row, column} objects"); + }, 'Arguments must be {row, column} objects'); assert.throws(() => { sumNode.descendantForPosition(); - }, "Arguments must be {row, column} objects"); + }, 'Arguments must be {row, column} objects'); }); }); - describe(".namedDescendantForPosition(min, max)", () => { - it("returns the smallest named node that spans the given range", () => { - tree = parser.parse("x10 + 1000"); + describe('.namedDescendantForPosition(min, max)', () => { + it('returns the smallest named node that spans the given range', () => { + tree = parser.parse('x10 + 1000'); const sumNode = tree.rootNode.firstChild; assert.equal( sumNode.namedDescendantForPosition( - { row: 0, column: 1 }, - { row: 0, column: 2 } + {row: 0, column: 1}, + {row: 0, column: 2}, ).type, - "identifier", + 'identifier', ); assert.equal( - sumNode.namedDescendantForPosition({ row: 0, column: 4 }).type, - 'binary_expression' + sumNode.namedDescendantForPosition({row: 0, column: 4}).type, + 'binary_expression', ); }); }); - describe(".hasError()", () => { - it("returns true if the node contains an error", () => { - tree = parser.parse("1 + 2 * * 3"); + describe('.hasError()', () => { + it('returns true if the node contains an error', () => { + tree = parser.parse('1 + 2 * * 3'); const node = tree.rootNode; assert.equal( node.toString(), - '(program (expression_statement (binary_expression left: (number) right: (binary_expression left: (number) (ERROR) right: (number)))))' + '(program (expression_statement (binary_expression left: (number) right: (binary_expression left: (number) (ERROR) right: (number)))))', ); const sum = node.firstChild.firstChild; @@ -268,13 +268,13 @@ describe("Node", () => { }); }); - describe(".isError()", () => { - it("returns true if the node is an error", () => { - tree = parser.parse("2 * * 3"); + describe('.isError()', () => { + it('returns true if the node is an error', () => { + tree = parser.parse('2 * * 3'); const node = tree.rootNode; assert.equal( node.toString(), - '(program (expression_statement (binary_expression left: (number) (ERROR) right: (number))))' + '(program (expression_statement (binary_expression left: (number) (ERROR) right: (number))))', ); const multi = node.firstChild.firstChild; @@ -286,17 +286,17 @@ describe("Node", () => { }); }); - describe(".isMissing()", () => { - it("returns true if the node is missing from the source and was inserted via error recovery", () => { - tree = parser.parse("(2 ||)"); + describe('.isMissing()', () => { + it('returns true if the node is missing from the source and was inserted via error recovery', () => { + tree = parser.parse('(2 ||)'); const node = tree.rootNode; assert.equal( node.toString(), - "(program (expression_statement (parenthesized_expression (binary_expression left: (number) right: (MISSING identifier)))))" + '(program (expression_statement (parenthesized_expression (binary_expression left: (number) right: (MISSING identifier)))))', ); const sum = node.firstChild.firstChild.firstNamedChild; - assert.equal(sum.type, 'binary_expression') + assert.equal(sum.type, 'binary_expression'); assert(sum.hasError()); assert(!sum.children[0].isMissing()); assert(!sum.children[1].isMissing()); @@ -304,33 +304,33 @@ describe("Node", () => { }); }); - describe(".text", () => { - const text = "α0 / b👎c👎"; + describe('.text', () => { + const text = 'α0 / b👎c👎'; Object.entries({ '.parse(String)': text, - '.parse(Function)': offset => text.substr(offset, 4) + '.parse(Function)': (offset) => text.substr(offset, 4), }).forEach(([method, parse]) => it(`returns the text of a node generated by ${method}`, async () => { - const [numeratorSrc, denominatorSrc] = text.split(/\s*\/\s+/) - tree = await parser.parse(text) + const [numeratorSrc, denominatorSrc] = text.split(/\s*\/\s+/); + tree = await parser.parse(text); const quotientNode = tree.rootNode.firstChild.firstChild; const [numerator, slash, denominator] = quotientNode.children; - assert.equal(text, tree.rootNode.text, 'root node text'); + assert.equal(text, tree.rootNode.text, 'root node text'); assert.equal(denominatorSrc, denominator.text, 'denominator text'); - assert.equal(text, quotientNode.text, 'quotient text'); - assert.equal(numeratorSrc, numerator.text, 'numerator text'); - assert.equal('/', slash.text, '"/" text'); - }) + assert.equal(text, quotientNode.text, 'quotient text'); + assert.equal(numeratorSrc, numerator.text, 'numerator text'); + assert.equal('/', slash.text, '"/" text'); + }), ); }); - describe(".parseState, .nextParseState", () => { - const text = "10 / 5"; + describe('.parseState, .nextParseState', () => { + const text = '10 / 5'; - it("returns node parse state ids", async () => { - tree = await parser.parse(text) + it('returns node parse state ids', async () => { + tree = await parser.parse(text); const quotientNode = tree.rootNode.firstChild.firstChild; const [numerator, slash, denominator] = quotientNode.children; @@ -340,15 +340,15 @@ describe("Node", () => { assert.isAbove(numerator.parseState, 0); assert.isAbove(slash.parseState, 0); assert.isAbove(denominator.parseState, 0); - }) + }); - it("returns next parse state equal to the language", async () => { + it('returns next parse state equal to the language', async () => { tree = await parser.parse(text); const quotientNode = tree.rootNode.firstChild.firstChild; - quotientNode.children.forEach(node => { + quotientNode.children.forEach((node) => { assert.equal( node.nextParseState, - JavaScript.nextState(node.parseState, node.grammarId) + JavaScript.nextState(node.parseState, node.grammarId), ); }); }); @@ -356,82 +356,82 @@ describe("Node", () => { describe('.descendantsOfType(type, min, max)', () => { it('finds all of the descendants of the given type in the given range', () => { - tree = parser.parse("a + 1 * b * 2 + c + 3"); + tree = parser.parse('a + 1 * b * 2 + c + 3'); const outerSum = tree.rootNode.firstChild.firstChild; - let descendants = outerSum.descendantsOfType('number', {row: 0, column: 2}, {row: 0, column: 15}) + let descendants = outerSum.descendantsOfType('number', {row: 0, column: 2}, {row: 0, column: 15}); assert.deepEqual( - descendants.map(node => node.startIndex), - [4, 12] + descendants.map((node) => node.startIndex), + [4, 12], ); assert.deepEqual( - descendants.map(node => node.endPosition), - [{row: 0, column: 5}, {row: 0, column: 13}] + descendants.map((node) => node.endPosition), + [{row: 0, column: 5}, {row: 0, column: 13}], ); - descendants = outerSum.descendantsOfType('identifier', {row: 0, column: 2}, {row: 0, column: 15}) + descendants = outerSum.descendantsOfType('identifier', {row: 0, column: 2}, {row: 0, column: 15}); assert.deepEqual( - descendants.map(node => node.startIndex), - [8] + descendants.map((node) => node.startIndex), + [8], ); - descendants = outerSum.descendantsOfType('identifier', {row: 0, column: 0}, {row: 0, column: 30}) + descendants = outerSum.descendantsOfType('identifier', {row: 0, column: 0}, {row: 0, column: 30}); assert.deepEqual( - descendants.map(node => node.startIndex), - [0, 8, 16] + descendants.map((node) => node.startIndex), + [0, 8, 16], ); - descendants = outerSum.descendantsOfType('number', {row: 0, column: 0}, {row: 0, column: 30}) + descendants = outerSum.descendantsOfType('number', {row: 0, column: 0}, {row: 0, column: 30}); assert.deepEqual( - descendants.map(node => node.startIndex), - [4, 12, 20] + descendants.map((node) => node.startIndex), + [4, 12, 20], ); descendants = outerSum.descendantsOfType( ['identifier', 'number'], {row: 0, column: 0}, - {row: 0, column: 30} - ) + {row: 0, column: 30}, + ); assert.deepEqual( - descendants.map(node => node.startIndex), - [0, 4, 8, 12, 16, 20] + descendants.map((node) => node.startIndex), + [0, 4, 8, 12, 16, 20], ); - descendants = outerSum.descendantsOfType('number') + descendants = outerSum.descendantsOfType('number'); assert.deepEqual( - descendants.map(node => node.startIndex), - [4, 12, 20] + descendants.map((node) => node.startIndex), + [4, 12, 20], ); - descendants = outerSum.firstChild.descendantsOfType('number', {row: 0, column: 0}, {row: 0, column: 30}) + descendants = outerSum.firstChild.descendantsOfType('number', {row: 0, column: 0}, {row: 0, column: 30}); assert.deepEqual( - descendants.map(node => node.startIndex), - [4, 12] + descendants.map((node) => node.startIndex), + [4, 12], ); - }) + }); }); describe.skip('.closest(type)', () => { it('returns the closest ancestor of the given type', () => { - tree = parser.parse("a(b + -d.e)"); - const property = tree.rootNode.descendantForIndex("a(b + -d.".length); + tree = parser.parse('a(b + -d.e)'); + const property = tree.rootNode.descendantForIndex('a(b + -d.'.length); assert.equal(property.type, 'property_identifier'); - const unary = property.closest('unary_expression') - assert.equal(unary.type, 'unary_expression') - assert.equal(unary.startIndex, 'a(b + '.length) - assert.equal(unary.endIndex, 'a(b + -d.e'.length) + const unary = property.closest('unary_expression'); + assert.equal(unary.type, 'unary_expression'); + assert.equal(unary.startIndex, 'a(b + '.length); + assert.equal(unary.endIndex, 'a(b + -d.e'.length); - const sum = property.closest(['binary_expression', 'call_expression']) - assert.equal(sum.type, 'binary_expression') - assert.equal(sum.startIndex, 2) - assert.equal(sum.endIndex, 'a(b + -d.e'.length) + const sum = property.closest(['binary_expression', 'call_expression']); + assert.equal(sum.type, 'binary_expression'); + assert.equal(sum.startIndex, 2); + assert.equal(sum.endIndex, 'a(b + -d.e'.length); }); it('throws an exception when an invalid argument is given', () => { - tree = parser.parse("a + 1 * b * 2 + c + 3"); - const number = tree.rootNode.descendantForIndex(4) + tree = parser.parse('a + 1 * b * 2 + c + 3'); + const number = tree.rootNode.descendantForIndex(4); - assert.throws(() => number.closest({a: 1}), /Argument must be a string or array of strings/) + assert.throws(() => number.closest({a: 1}), /Argument must be a string or array of strings/); }); }); diff --git a/lib/binding_web/test/parser-test.js b/lib/binding_web/test/parser-test.js index a25e5dc5..2a703eaf 100644 --- a/lib/binding_web/test/parser-test.js +++ b/lib/binding_web/test/parser-test.js @@ -1,11 +1,11 @@ const {assert} = require('chai'); -let Parser, JavaScript, languageURL; +let Parser; let JavaScript; let languageURL; -describe("Parser", () => { +describe('Parser', () => { let parser; before(async () => - ({Parser, JavaScript, languageURL} = await require('./helper')) + ({Parser, JavaScript, languageURL} = await require('./helper')), ); beforeEach(() => { @@ -13,11 +13,11 @@ describe("Parser", () => { }); afterEach(() => { - parser.delete() + parser.delete(); }); - describe(".setLanguage", () => { - it("allows setting the language to null", () => { + describe('.setLanguage', () => { + it('allows setting the language to null', () => { assert.equal(parser.getLanguage(), null); parser.setLanguage(JavaScript); assert.equal(parser.getLanguage(), JavaScript); @@ -25,112 +25,114 @@ describe("Parser", () => { assert.equal(parser.getLanguage(), null); }); - it("throws an exception when the given object is not a tree-sitter language", () => { + it('throws an exception when the given object is not a tree-sitter language', () => { assert.throws(() => parser.setLanguage({}), /Argument must be a Language/); assert.throws(() => parser.setLanguage(1), /Argument must be a Language/); }); }); - describe(".setLogger", () => { + describe('.setLogger', () => { beforeEach(() => { - parser.setLanguage(JavaScript) + parser.setLanguage(JavaScript); }); - it("calls the given callback for each parse event", () => { + it('calls the given callback for each parse event', () => { const debugMessages = []; parser.setLogger((message) => debugMessages.push(message)); - parser.parse("a + b + c"); + parser.parse('a + b + c'); assert.includeMembers(debugMessages, [ - "skip character:' '", - "consume character:'b'", - "reduce sym:program, child_count:1", - "accept" + 'skip character:\' \'', + 'consume character:\'b\'', + 'reduce sym:program, child_count:1', + 'accept', ]); }); - it("allows the callback to be retrieved later", () => { - const callback = () => {} + it('allows the callback to be retrieved later', () => { + const callback = () => {}; parser.setLogger(callback); assert.equal(parser.getLogger(), callback); parser.setLogger(false); assert.equal(parser.getLogger(), null); }); - it("disables debugging when given a falsy value", () => { + it('disables debugging when given a falsy value', () => { const debugMessages = []; parser.setLogger((message) => debugMessages.push(message)); parser.setLogger(false); - parser.parse("a + b * c"); + parser.parse('a + b * c'); assert.equal(debugMessages.length, 0); }); - it("throws an error when given a truthy value that isn't a function ", () => { + it('throws an error when given a truthy value that isn\'t a function ', () => { assert.throws( - () => parser.setLogger("5"), - "Logger callback must be a function" + () => parser.setLogger('5'), + 'Logger callback must be a function', ); }); - it("rethrows errors thrown by the logging callback", () => { - const error = new Error("The error message"); - parser.setLogger((msg, params) => { throw error; }); + it('rethrows errors thrown by the logging callback', () => { + const error = new Error('The error message'); + parser.setLogger((msg, params) => { + throw error; + }); assert.throws( - () => parser.parse("ok;"), - "The error message" + () => parser.parse('ok;'), + 'The error message', ); }); }); - describe(".parse", () => { + describe('.parse', () => { let tree; beforeEach(() => { tree = null; - parser.setLanguage(JavaScript) + parser.setLanguage(JavaScript); }); afterEach(() => { if (tree) tree.delete(); }); - it("reads from the given input", () => { - const parts = ["first", "_", "second", "_", "third"]; + it('reads from the given input', () => { + const parts = ['first', '_', 'second', '_', 'third']; tree = parser.parse(() => parts.shift()); - assert.equal(tree.rootNode.toString(), "(program (expression_statement (identifier)))"); + assert.equal(tree.rootNode.toString(), '(program (expression_statement (identifier)))'); }); - it("stops reading when the input callback return something that's not a string", () => { - const parts = ["abc", "def", "ghi", {}, {}, {}, "second-word", " "]; + it('stops reading when the input callback return something that\'s not a string', () => { + const parts = ['abc', 'def', 'ghi', {}, {}, {}, 'second-word', ' ']; tree = parser.parse(() => parts.shift()); assert.equal( tree.rootNode.toString(), - "(program (expression_statement (identifier)))" + '(program (expression_statement (identifier)))', ); assert.equal(tree.rootNode.endIndex, 9); assert.equal(parts.length, 2); }); - it("throws an exception when the given input is not a function", () => { - assert.throws(() => parser.parse(null), "Argument must be a string or a function"); - assert.throws(() => parser.parse(5), "Argument must be a string or a function"); - assert.throws(() => parser.parse({}), "Argument must be a string or a function"); + it('throws an exception when the given input is not a function', () => { + assert.throws(() => parser.parse(null), 'Argument must be a string or a function'); + assert.throws(() => parser.parse(5), 'Argument must be a string or a function'); + assert.throws(() => parser.parse({}), 'Argument must be a string or a function'); }); - it("handles long input strings", () => { + it('handles long input strings', () => { const repeatCount = 10000; - const inputString = "[" + "0,".repeat(repeatCount) + "]"; + const inputString = '[' + '0,'.repeat(repeatCount) + ']'; tree = parser.parse(inputString); - assert.equal(tree.rootNode.type, "program"); + assert.equal(tree.rootNode.type, 'program'); assert.equal(tree.rootNode.firstChild.firstChild.namedChildCount, repeatCount); }).timeout(5000); - it("can use the bash parser", async () => { + it('can use the bash parser', async () => { parser.setLanguage(await Parser.Language.load(languageURL('bash'))); - tree = parser.parse("FOO=bar echo < err.txt > hello.txt \nhello${FOO}\nEOF"); + tree = parser.parse('FOO=bar echo < err.txt > hello.txt \nhello${FOO}\nEOF'); assert.equal( tree.rootNode.toString(), - '(program ' + + '(program ' + '(redirected_statement ' + 'body: (command ' + '(variable_assignment name: (variable_name) value: (word)) ' + @@ -139,13 +141,13 @@ describe("Parser", () => { 'redirect: (file_redirect descriptor: (file_descriptor) destination: (word)) ' + 'redirect: (file_redirect destination: (word)) ' + '(heredoc_body ' + - '(expansion (variable_name)) (heredoc_content)) (heredoc_end))))' + '(expansion (variable_name)) (heredoc_content)) (heredoc_end))))', ); }).timeout(5000); - it("can use the c++ parser", async () => { + it('can use the c++ parser', async () => { parser.setLanguage(await Parser.Language.load(languageURL('cpp'))); - tree = parser.parse("const char *s = R\"EOF(HELLO WORLD)EOF\";"); + tree = parser.parse('const char *s = R"EOF(HELLO WORLD)EOF";'); assert.equal( tree.rootNode.toString(), '(translation_unit (declaration ' + @@ -153,22 +155,22 @@ describe("Parser", () => { 'type: (primitive_type) ' + 'declarator: (init_declarator ' + 'declarator: (pointer_declarator declarator: (identifier)) ' + - 'value: (raw_string_literal delimiter: (raw_string_delimiter) (raw_string_content) (raw_string_delimiter)))))' + 'value: (raw_string_literal delimiter: (raw_string_delimiter) (raw_string_content) (raw_string_delimiter)))))', ); }).timeout(5000); - it("can use the HTML parser", async () => { + it('can use the HTML parser', async () => { parser.setLanguage(await Parser.Language.load(languageURL('html'))); - tree = parser.parse("
"); + tree = parser.parse('
'); assert.equal( tree.rootNode.toString(), - '(fragment (element (start_tag (tag_name)) (element (start_tag (tag_name)) (element (start_tag (tag_name)) (end_tag (tag_name))) (end_tag (tag_name))) (end_tag (tag_name))))' + '(fragment (element (start_tag (tag_name)) (element (start_tag (tag_name)) (element (start_tag (tag_name)) (end_tag (tag_name))) (end_tag (tag_name))) (end_tag (tag_name))))', ); }).timeout(5000); - it("can use the python parser", async () => { + it('can use the python parser', async () => { parser.setLanguage(await Parser.Language.load(languageURL('python'))); - tree = parser.parse("class A:\n def b():\n c()"); + tree = parser.parse('class A:\n def b():\n c()'); assert.equal( tree.rootNode.toString(), '(module (class_definition ' + @@ -179,25 +181,25 @@ describe("Parser", () => { 'parameters: (parameters) ' + 'body: (block (expression_statement (call ' + 'function: (identifier) ' + - 'arguments: (argument_list))))))))' + 'arguments: (argument_list))))))))', ); }).timeout(5000); - it("can use the rust parser", async () => { + it('can use the rust parser', async () => { parser.setLanguage(await Parser.Language.load(languageURL('rust'))); - tree = parser.parse("const x: &'static str = r###\"hello\"###;"); + tree = parser.parse('const x: &\'static str = r###"hello"###;'); assert.equal( tree.rootNode.toString(), '(source_file (const_item ' + 'name: (identifier) ' + 'type: (reference_type (lifetime (identifier)) type: (primitive_type)) ' + - 'value: (raw_string_literal)))' + 'value: (raw_string_literal)))', ); }).timeout(5000); - it("can use the typescript parser", async () => { + it('can use the typescript parser', async () => { parser.setLanguage(await Parser.Language.load(languageURL('typescript'))); - tree = parser.parse("a()\nb()\n[c]"); + tree = parser.parse('a()\nb()\n[c]'); assert.equal( tree.rootNode.toString(), '(program ' + @@ -206,13 +208,13 @@ describe("Parser", () => { 'object: (call_expression ' + 'function: (identifier) ' + 'arguments: (arguments)) ' + - 'index: (identifier))))' + 'index: (identifier))))', ); }).timeout(5000); - it("can use the tsx parser", async () => { + it('can use the tsx parser', async () => { parser.setLanguage(await Parser.Language.load(languageURL('tsx'))); - tree = parser.parse("a()\nb()\n[c]"); + tree = parser.parse('a()\nb()\n[c]'); assert.equal( tree.rootNode.toString(), '(program ' + @@ -221,17 +223,17 @@ describe("Parser", () => { 'object: (call_expression ' + 'function: (identifier) ' + 'arguments: (arguments)) ' + - 'index: (identifier))))' + 'index: (identifier))))', ); }).timeout(5000); it('parses only the text within the `includedRanges` if they are specified', () => { - const sourceCode = "<% foo() %> <% bar %>"; + const sourceCode = '<% foo() %> <% bar %>'; const start1 = sourceCode.indexOf('foo'); - const end1 = start1 + 5 + const end1 = start1 + 5; const start2 = sourceCode.indexOf('bar'); - const end2 = start2 + 3 + const end2 = start2 + 3; const tree = parser.parse(sourceCode, null, { includedRanges: [ @@ -239,20 +241,21 @@ describe("Parser", () => { startIndex: start1, endIndex: end1, startPosition: {row: 0, column: start1}, - endPosition: {row: 0, column: end1} + endPosition: {row: 0, column: end1}, }, { startIndex: start2, endIndex: end2, startPosition: {row: 0, column: start2}, - endPosition: {row: 0, column: end2} + endPosition: {row: 0, column: end2}, }, - ] + ], }); assert.equal( tree.rootNode.toString(), - '(program (expression_statement (call_expression function: (identifier) arguments: (arguments))) (expression_statement (identifier)))' + '(program (expression_statement (call_expression function: (identifier) arguments: (arguments))) (expression_statement (identifier)))', ); - }) - });}); + }); + }); +}); diff --git a/lib/binding_web/test/query-test.js b/lib/binding_web/test/query-test.js index f53b8d15..40913152 100644 --- a/lib/binding_web/test/query-test.js +++ b/lib/binding_web/test/query-test.js @@ -1,10 +1,10 @@ -const { assert } = require("chai"); -let Parser, JavaScript; +const {assert} = require('chai'); +let Parser; let JavaScript; -describe("Query", () => { - let parser, tree, query; +describe('Query', () => { + let parser; let tree; let query; - before(async () => ({ Parser, JavaScript } = await require("./helper"))); + before(async () => ({Parser, JavaScript} = await require('./helper'))); beforeEach(() => { parser = new Parser().setLanguage(JavaScript); @@ -16,73 +16,73 @@ describe("Query", () => { if (query) query.delete(); }); - describe("construction", () => { - it("throws an error on invalid patterns", () => { + describe('construction', () => { + it('throws an error on invalid patterns', () => { assert.throws(() => { - JavaScript.query("(function_declaration wat)"); - }, "Bad syntax at offset 22: 'wat)'..."); + JavaScript.query('(function_declaration wat)'); + }, 'Bad syntax at offset 22: \'wat)\'...'); assert.throws(() => { - JavaScript.query("(non_existent)"); - }, "Bad node name 'non_existent'"); + JavaScript.query('(non_existent)'); + }, 'Bad node name \'non_existent\''); assert.throws(() => { - JavaScript.query("(a)"); - }, "Bad node name 'a'"); + JavaScript.query('(a)'); + }, 'Bad node name \'a\''); assert.throws(() => { - JavaScript.query("(function_declaration non_existent:(identifier))"); - }, "Bad field name 'non_existent'"); + JavaScript.query('(function_declaration non_existent:(identifier))'); + }, 'Bad field name \'non_existent\''); assert.throws(() => { - JavaScript.query("(function_declaration name:(statement_block))"); - }, "Bad pattern structure at offset 22: 'name:(statement_block))'"); + JavaScript.query('(function_declaration name:(statement_block))'); + }, 'Bad pattern structure at offset 22: \'name:(statement_block))\''); }); - it("throws an error on invalid predicates", () => { + it('throws an error on invalid predicates', () => { assert.throws(() => { - JavaScript.query("((identifier) @abc (#eq? @ab hi))"); - }, "Bad capture name @ab"); + JavaScript.query('((identifier) @abc (#eq? @ab hi))'); + }, 'Bad capture name @ab'); assert.throws(() => { - JavaScript.query("((identifier) @abc (#eq? @ab hi))"); - }, "Bad capture name @ab"); + JavaScript.query('((identifier) @abc (#eq? @ab hi))'); + }, 'Bad capture name @ab'); assert.throws(() => { - JavaScript.query("((identifier) @abc (#eq?))"); - }, "Wrong number of arguments to `#eq?` predicate. Expected 2, got 0"); + JavaScript.query('((identifier) @abc (#eq?))'); + }, 'Wrong number of arguments to `#eq?` predicate. Expected 2, got 0'); assert.throws(() => { - JavaScript.query("((identifier) @a (eq? @a @a @a))"); - }, "Wrong number of arguments to `#eq?` predicate. Expected 2, got 3"); + JavaScript.query('((identifier) @a (eq? @a @a @a))'); + }, 'Wrong number of arguments to `#eq?` predicate. Expected 2, got 3'); }); }); - describe(".matches", () => { - it("returns all of the matches for the given query", () => { - tree = parser.parse("function one() { two(); function three() {} }"); + describe('.matches', () => { + it('returns all of the matches for the given query', () => { + tree = parser.parse('function one() { two(); function three() {} }'); query = JavaScript.query(` (function_declaration name: (identifier) @fn-def) (call_expression function: (identifier) @fn-ref) `); const matches = query.matches(tree.rootNode); assert.deepEqual(formatMatches(matches), [ - { pattern: 0, captures: [{ name: "fn-def", text: "one" }] }, - { pattern: 1, captures: [{ name: "fn-ref", text: "two" }] }, - { pattern: 0, captures: [{ name: "fn-def", text: "three" }] }, + {pattern: 0, captures: [{name: 'fn-def', text: 'one'}]}, + {pattern: 1, captures: [{name: 'fn-ref', text: 'two'}]}, + {pattern: 0, captures: [{name: 'fn-def', text: 'three'}]}, ]); }); - it("can search in a specified ranges", () => { - tree = parser.parse("[a, b,\nc, d,\ne, f,\ng, h]"); - query = JavaScript.query("(identifier) @element"); + it('can search in a specified ranges', () => { + tree = parser.parse('[a, b,\nc, d,\ne, f,\ng, h]'); + query = JavaScript.query('(identifier) @element'); const matches = query.matches( tree.rootNode, - { row: 1, column: 1 }, - { row: 3, column: 1 } + {row: 1, column: 1}, + {row: 3, column: 1}, ); assert.deepEqual(formatMatches(matches), [ - { pattern: 0, captures: [{ name: "element", text: "d" }] }, - { pattern: 0, captures: [{ name: "element", text: "e" }] }, - { pattern: 0, captures: [{ name: "element", text: "f" }] }, - { pattern: 0, captures: [{ name: "element", text: "g" }] }, + {pattern: 0, captures: [{name: 'element', text: 'd'}]}, + {pattern: 0, captures: [{name: 'element', text: 'e'}]}, + {pattern: 0, captures: [{name: 'element', text: 'f'}]}, + {pattern: 0, captures: [{name: 'element', text: 'g'}]}, ]); }); - it("handles predicates that compare the text of capture to literal strings", () => { + it('handles predicates that compare the text of capture to literal strings', () => { tree = parser.parse(` giraffe(1, 2, []); helment([false]); @@ -103,14 +103,14 @@ describe("Query", () => { const matches = query.matches(tree.rootNode); assert.deepEqual(formatMatches(matches), [ - { pattern: 0, captures: [{ name: "name", text: "giraffe" }] }, - { pattern: 0, captures: [{ name: "name", text: "gross" }] }, + {pattern: 0, captures: [{name: 'name', text: 'giraffe'}]}, + {pattern: 0, captures: [{name: 'name', text: 'gross'}]}, ]); }); }); - describe(".captures", () => { - it("returns all of the captures for the given query, in order", () => { + describe('.captures', () => { + it('returns all of the captures for the given query, in order', () => { tree = parser.parse(` a({ bc: function de() { @@ -138,22 +138,22 @@ describe("Query", () => { const captures = query.captures(tree.rootNode); assert.deepEqual(formatCaptures(captures), [ - { name: "method.def", text: "bc" }, - { name: "delimiter", text: ":" }, - { name: "method.alias", text: "de" }, - { name: "function.def", text: "fg" }, - { name: "operator", text: "=" }, - { name: "function.alias", text: "hi" }, - { name: "method.def", text: "jk" }, - { name: "delimiter", text: ":" }, - { name: "method.alias", text: "lm" }, - { name: "function.def", text: "no" }, - { name: "operator", text: "=" }, - { name: "function.alias", text: "pq" }, + {name: 'method.def', text: 'bc'}, + {name: 'delimiter', text: ':'}, + {name: 'method.alias', text: 'de'}, + {name: 'function.def', text: 'fg'}, + {name: 'operator', text: '='}, + {name: 'function.alias', text: 'hi'}, + {name: 'method.def', text: 'jk'}, + {name: 'delimiter', text: ':'}, + {name: 'method.alias', text: 'lm'}, + {name: 'function.def', text: 'no'}, + {name: 'operator', text: '='}, + {name: 'function.alias', text: 'pq'}, ]); }); - it("handles conditions that compare the text of capture to literal strings", () => { + it('handles conditions that compare the text of capture to literal strings', () => { tree = parser.parse(` lambda panda @@ -179,20 +179,20 @@ describe("Query", () => { const captures = query.captures(tree.rootNode); assert.deepEqual(formatCaptures(captures), [ - { name: "variable", text: "panda" }, - { name: "variable", text: "toad" }, - { name: "variable", text: "ab" }, - { name: "variable", text: "require" }, - { name: "function.builtin", text: "require" }, - { name: "variable", text: "Cd" }, - { name: "constructor", text: "Cd" }, - { name: "variable", text: "EF" }, - { name: "constructor", text: "EF" }, - { name: "constant", text: "EF" }, + {name: 'variable', text: 'panda'}, + {name: 'variable', text: 'toad'}, + {name: 'variable', text: 'ab'}, + {name: 'variable', text: 'require'}, + {name: 'function.builtin', text: 'require'}, + {name: 'variable', text: 'Cd'}, + {name: 'constructor', text: 'Cd'}, + {name: 'variable', text: 'EF'}, + {name: 'constructor', text: 'EF'}, + {name: 'constant', text: 'EF'}, ]); }); - it("handles conditions that compare the text of capture to each other", () => { + it('handles conditions that compare the text of capture to each other', () => { tree = parser.parse(` ab = abc + 1; def = de + 1; @@ -211,12 +211,12 @@ describe("Query", () => { const captures = query.captures(tree.rootNode); assert.deepEqual(formatCaptures(captures), [ - { name: "id1", text: "ghi" }, - { name: "id2", text: "ghi" }, + {name: 'id1', text: 'ghi'}, + {name: 'id2', text: 'ghi'}, ]); }); - it("handles patterns with properties", () => { + it('handles patterns with properties', () => { tree = parser.parse(`a(b.c);`); query = JavaScript.query(` ((call_expression (identifier) @func) @@ -230,18 +230,18 @@ describe("Query", () => { const captures = query.captures(tree.rootNode); assert.deepEqual(formatCaptures(captures), [ - { name: "func", text: "a", setProperties: { foo: null, bar: "baz" } }, + {name: 'func', text: 'a', setProperties: {foo: null, bar: 'baz'}}, { - name: "prop", - text: "c", - assertedProperties: { foo: null }, - refutedProperties: { bar: "baz" }, + name: 'prop', + text: 'c', + assertedProperties: {foo: null}, + refutedProperties: {bar: 'baz'}, }, ]); assert.ok(!query.didExceedMatchLimit()); }); - it("detects queries with too many permutations to track", () => { + it('detects queries with too many permutations to track', () => { tree = parser.parse(` [ hello, hello, hello, hello, hello, hello, hello, hello, hello, hello, @@ -256,11 +256,11 @@ describe("Query", () => { (array (identifier) @pre (identifier) @post) `); - const captures = query.captures(tree.rootNode, null, null, { matchLimit: 32 }); + query.captures(tree.rootNode, null, null, {matchLimit: 32}); assert.ok(query.didExceedMatchLimit()); }); - it("handles quantified captures properly", () => { + it('handles quantified captures properly', () => { let captures; tree = parser.parse(` @@ -276,7 +276,7 @@ describe("Query", () => { ) `); - let expectCount = (tree, queryText, expectedCount) => { + const expectCount = (tree, queryText, expectedCount) => { query = JavaScript.query(queryText); captures = query.captures(tree.rootNode, null, null); assert.equal(captures.length, expectedCount); @@ -284,68 +284,68 @@ describe("Query", () => { expectCount( tree, - ` ( (comment)+ @foo (#any-eq? @foo "/// foo") ) `, - 3 + `((comment)+ @foo (#any-eq? @foo "/// foo"))`, + 3, ); expectCount( tree, - ` ( (comment)+ @foo (#eq? @foo "/// foo") ) `, - 0 + `((comment)+ @foo (#eq? @foo "/// foo"))`, + 0, ); expectCount( tree, - ` ( (comment)+ @foo (#any-not-eq? @foo "/// foo") ) `, - 3 + `((comment)+ @foo (#any-not-eq? @foo "/// foo"))`, + 3, ); expectCount( tree, - ` ( (comment)+ @foo (#not-eq? @foo "/// foo") ) `, - 0 + `((comment)+ @foo (#not-eq? @foo "/// foo"))`, + 0, ); expectCount( tree, - ` ( (comment)+ @foo (#match? @foo "^/// foo") ) `, - 0 + `((comment)+ @foo (#match? @foo "^/// foo"))`, + 0, ); expectCount( tree, - ` ( (comment)+ @foo (#any-match? @foo "^/// foo") ) `, - 3 + `((comment)+ @foo (#any-match? @foo "^/// foo"))`, + 3, ); expectCount( tree, - ` ( (comment)+ @foo (#not-match? @foo "^/// foo") ) `, - 0 + `((comment)+ @foo (#not-match? @foo "^/// foo"))`, + 0, ); expectCount( tree, - ` ( (comment)+ @foo (#not-match? @foo "fsdfsdafdfs") ) `, - 3 + `((comment)+ @foo (#not-match? @foo "fsdfsdafdfs"))`, + 3, ); expectCount( tree, - ` ( (comment)+ @foo (#any-not-match? @foo "^///") ) `, - 0 + `((comment)+ @foo (#any-not-match? @foo "^///"))`, + 0, ); expectCount( tree, - ` ( (comment)+ @foo (#any-not-match? @foo "^/// foo") ) `, - 3 + `((comment)+ @foo (#any-not-match? @foo "^/// foo"))`, + 3, ); - }) + }); }); - describe(".predicatesForPattern(index)", () => { - it("returns all of the predicates as objects", () => { + describe('.predicatesForPattern(index)', () => { + it('returns all of the predicates as objects', () => { query = JavaScript.query(` ( (binary_expression @@ -364,26 +364,26 @@ describe("Query", () => { assert.deepEqual(query.predicatesForPattern(0), [ { - operator: "something?", + operator: 'something?', operands: [ - { type: "capture", name: "a" }, - { type: "capture", name: "b" }, + {type: 'capture', name: 'a'}, + {type: 'capture', name: 'b'}, ], }, { - operator: "something-else?", + operator: 'something-else?', operands: [ - { type: "capture", name: "a" }, - { type: "string", value: "A" }, - { type: "capture", name: "b" }, - { type: "string", value: "B" }, + {type: 'capture', name: 'a'}, + {type: 'string', value: 'A'}, + {type: 'capture', name: 'b'}, + {type: 'string', value: 'B'}, ], }, ]); assert.deepEqual(query.predicatesForPattern(1), [ { - operator: "hello!", - operands: [{ type: "capture", name: "c" }], + operator: 'hello!', + operands: [{type: 'capture', name: 'c'}], }, ]); assert.deepEqual(query.predicatesForPattern(2), []); @@ -392,7 +392,7 @@ describe("Query", () => { }); function formatMatches(matches) { - return matches.map(({ pattern, captures }) => ({ + return matches.map(({pattern, captures}) => ({ pattern, captures: formatCaptures(captures), })); diff --git a/lib/binding_web/test/tree-test.js b/lib/binding_web/test/tree-test.js index a98d216a..bf4a68e8 100644 --- a/lib/binding_web/test/tree-test.js +++ b/lib/binding_web/test/tree-test.js @@ -1,11 +1,11 @@ const {assert} = require('chai'); -let Parser, JavaScript; +let Parser; let JavaScript; -describe("Tree", () => { - let parser, tree; +describe('Tree', () => { + let parser; let tree; before(async () => - ({Parser, JavaScript} = await require('./helper')) + ({Parser, JavaScript} = await require('./helper')), ); beforeEach(() => { @@ -18,14 +18,14 @@ describe("Tree", () => { }); describe('.edit', () => { - let input, edit + let input; let edit; it('updates the positions of nodes', () => { input = 'abc + cde'; tree = parser.parse(input); assert.equal( tree.rootNode.toString(), - "(program (expression_statement (binary_expression left: (identifier) right: (identifier))))" + '(program (expression_statement (binary_expression left: (identifier) right: (identifier))))', ); let sumNode = tree.rootNode.firstChild.firstChild; @@ -51,17 +51,17 @@ describe("Tree", () => { tree = parser.parse(input, tree); assert.equal( tree.rootNode.toString(), - "(program (expression_statement (binary_expression left: (binary_expression left: (identifier) right: (identifier)) right: (identifier))))" + '(program (expression_statement (binary_expression left: (binary_expression left: (identifier) right: (identifier)) right: (identifier))))', ); }); - it("handles non-ascii characters", () => { + it('handles non-ascii characters', () => { input = 'αβδ + cde'; tree = parser.parse(input); assert.equal( tree.rootNode.toString(), - "(program (expression_statement (binary_expression left: (identifier) right: (identifier))))" + '(program (expression_statement (binary_expression left: (identifier) right: (identifier))))', ); let variableNode = tree.rootNode.firstChild.firstChild.lastChild; @@ -76,65 +76,65 @@ describe("Tree", () => { tree = parser.parse(input, tree); assert.equal( tree.rootNode.toString(), - "(program (expression_statement (binary_expression left: (binary_expression left: (identifier) right: (identifier)) right: (identifier))))" + '(program (expression_statement (binary_expression left: (binary_expression left: (identifier) right: (identifier)) right: (identifier))))', ); }); }); - describe(".getChangedRanges(previous)", () => { - it("reports the ranges of text whose syntactic meaning has changed", () => { - let sourceCode = "abcdefg + hij"; + describe('.getChangedRanges(previous)', () => { + it('reports the ranges of text whose syntactic meaning has changed', () => { + let sourceCode = 'abcdefg + hij'; tree = parser.parse(sourceCode); assert.equal( tree.rootNode.toString(), - "(program (expression_statement (binary_expression left: (identifier) right: (identifier))))" + '(program (expression_statement (binary_expression left: (identifier) right: (identifier))))', ); - sourceCode = "abc + defg + hij"; + sourceCode = 'abc + defg + hij'; tree.edit({ startIndex: 2, oldEndIndex: 2, newEndIndex: 5, - startPosition: { row: 0, column: 2 }, - oldEndPosition: { row: 0, column: 2 }, - newEndPosition: { row: 0, column: 5 } + startPosition: {row: 0, column: 2}, + oldEndPosition: {row: 0, column: 2}, + newEndPosition: {row: 0, column: 5}, }); const tree2 = parser.parse(sourceCode, tree); assert.equal( tree2.rootNode.toString(), - "(program (expression_statement (binary_expression left: (binary_expression left: (identifier) right: (identifier)) right: (identifier))))" + '(program (expression_statement (binary_expression left: (binary_expression left: (identifier) right: (identifier)) right: (identifier))))', ); const ranges = tree.getChangedRanges(tree2); assert.deepEqual(ranges, [ { startIndex: 0, - endIndex: "abc + defg".length, - startPosition: { row: 0, column: 0 }, - endPosition: { row: 0, column: "abc + defg".length } - } + endIndex: 'abc + defg'.length, + startPosition: {row: 0, column: 0}, + endPosition: {row: 0, column: 'abc + defg'.length}, + }, ]); tree2.delete(); }); it('throws an exception if the argument is not a tree', () => { - tree = parser.parse("abcdefg + hij"); + tree = parser.parse('abcdefg + hij'); assert.throws(() => { tree.getChangedRanges({}); }, /Argument must be a Tree/); - }) + }); }); - describe(".walk()", () => { - let cursor + describe('.walk()', () => { + let cursor; afterEach(() => { cursor.delete(); - }) + }); it('returns a cursor that can be used to walk the tree', () => { tree = parser.parse('a * b + c / d'); @@ -146,7 +146,7 @@ describe("Tree", () => { startPosition: {row: 0, column: 0}, endPosition: {row: 0, column: 13}, startIndex: 0, - endIndex: 13 + endIndex: 13, }); assert(cursor.gotoFirstChild()); @@ -156,7 +156,7 @@ describe("Tree", () => { startPosition: {row: 0, column: 0}, endPosition: {row: 0, column: 13}, startIndex: 0, - endIndex: 13 + endIndex: 13, }); assert(cursor.gotoFirstChild()); @@ -166,7 +166,7 @@ describe("Tree", () => { startPosition: {row: 0, column: 0}, endPosition: {row: 0, column: 13}, startIndex: 0, - endIndex: 13 + endIndex: 13, }); assert(cursor.gotoFirstChild()); @@ -176,7 +176,7 @@ describe("Tree", () => { startPosition: {row: 0, column: 0}, endPosition: {row: 0, column: 5}, startIndex: 0, - endIndex: 5 + endIndex: 5, }); assert(cursor.gotoFirstChild()); @@ -187,10 +187,10 @@ describe("Tree", () => { startPosition: {row: 0, column: 0}, endPosition: {row: 0, column: 1}, startIndex: 0, - endIndex: 1 + endIndex: 1, }); - assert(!cursor.gotoFirstChild()) + assert(!cursor.gotoFirstChild()); assert(cursor.gotoNextSibling()); assert.equal(cursor.nodeText, '*'); assertCursorState(cursor, { @@ -199,7 +199,7 @@ describe("Tree", () => { startPosition: {row: 0, column: 2}, endPosition: {row: 0, column: 3}, startIndex: 2, - endIndex: 3 + endIndex: 3, }); assert(cursor.gotoNextSibling()); @@ -210,7 +210,7 @@ describe("Tree", () => { startPosition: {row: 0, column: 4}, endPosition: {row: 0, column: 5}, startIndex: 4, - endIndex: 5 + endIndex: 5, }); assert(!cursor.gotoNextSibling()); @@ -221,7 +221,7 @@ describe("Tree", () => { startPosition: {row: 0, column: 0}, endPosition: {row: 0, column: 5}, startIndex: 0, - endIndex: 5 + endIndex: 5, }); assert(cursor.gotoNextSibling()); @@ -231,7 +231,7 @@ describe("Tree", () => { startPosition: {row: 0, column: 6}, endPosition: {row: 0, column: 7}, startIndex: 6, - endIndex: 7 + endIndex: 7, }); assert(cursor.gotoNextSibling()); @@ -241,7 +241,7 @@ describe("Tree", () => { startPosition: {row: 0, column: 8}, endPosition: {row: 0, column: 13}, startIndex: 8, - endIndex: 13 + endIndex: 13, }); { @@ -255,7 +255,7 @@ describe("Tree", () => { startPosition: {row: 0, column: 6}, endPosition: {row: 0, column: 7}, startIndex: 6, - endIndex: 7 + endIndex: 7, }); assert(copy.gotoPreviousSibling()); @@ -265,28 +265,28 @@ describe("Tree", () => { startPosition: {row: 0, column: 0}, endPosition: {row: 0, column: 5}, startIndex: 0, - endIndex: 5 + endIndex: 5, }); assert(copy.gotoLastChild()); assertCursorState(copy, { - nodeType: "identifier", + nodeType: 'identifier', nodeIsNamed: true, startPosition: {row: 0, column: 4}, endPosition: {row: 0, column: 5}, startIndex: 4, - endIndex: 5 - }) + endIndex: 5, + }); assert(copy.gotoParent()); assert(copy.gotoParent()); - assert.equal(copy.nodeType, 'binary_expression') + assert.equal(copy.nodeType, 'binary_expression'); assert(copy.gotoParent()); - assert.equal(copy.nodeType, 'expression_statement') + assert.equal(copy.nodeType, 'expression_statement'); assert(copy.gotoParent()); - assert.equal(copy.nodeType, 'program') + assert.equal(copy.nodeType, 'program'); assert(!copy.gotoParent()); - } + } // const childIndex = cursor.gotoFirstChildForIndex(12); // assertCursorState(cursor, { @@ -302,11 +302,11 @@ describe("Tree", () => { // assert(cursor.gotoParent()); assert(cursor.gotoParent()); - assert.equal(cursor.nodeType, 'binary_expression') + assert.equal(cursor.nodeType, 'binary_expression'); assert(cursor.gotoParent()); - assert.equal(cursor.nodeType, 'expression_statement') + assert.equal(cursor.nodeType, 'expression_statement'); assert(cursor.gotoParent()); - assert.equal(cursor.nodeType, 'program') + assert.equal(cursor.nodeType, 'program'); assert(!cursor.gotoParent()); }); @@ -350,31 +350,31 @@ describe("Tree", () => { startPosition: {row: 0, column: 0}, endPosition: {row: 0, column: 5}, startIndex: 0, - endIndex: 5 + endIndex: 5, }); - cursor.gotoFirstChild() + cursor.gotoFirstChild(); assertCursorState(cursor, { nodeType: 'identifier', nodeIsNamed: true, startPosition: {row: 0, column: 0}, endPosition: {row: 0, column: 1}, startIndex: 0, - endIndex: 1 + endIndex: 1, }); assert(cursor.gotoParent()); assert(!cursor.gotoParent()); - }) + }); }); - describe(".copy", () => { - it("creates another tree that remains stable if the original tree is edited", () => { + describe('.copy', () => { + it('creates another tree that remains stable if the original tree is edited', () => { input = 'abc + cde'; tree = parser.parse(input); assert.equal( tree.rootNode.toString(), - "(program (expression_statement (binary_expression left: (identifier) right: (identifier))))" + '(program (expression_statement (binary_expression left: (identifier) right: (identifier))))', ); const tree2 = tree.copy(); @@ -386,10 +386,10 @@ describe("Tree", () => { const leftNode2 = tree2.rootNode.firstChild.firstChild.firstChild; const rightNode = tree.rootNode.firstChild.firstChild.lastChild; const rightNode2 = tree2.rootNode.firstChild.firstChild.lastChild; - assert.equal(leftNode.endIndex, 6) - assert.equal(leftNode2.endIndex, 3) - assert.equal(rightNode.startIndex, 9) - assert.equal(rightNode2.startIndex, 6) + assert.equal(leftNode.endIndex, 6); + assert.equal(leftNode2.endIndex, 3); + assert.equal(rightNode.startIndex, 9); + assert.equal(rightNode2.startIndex, 6); }); }); }); @@ -406,16 +406,16 @@ function spliceInput(input, startIndex, lengthRemoved, newText) { { startIndex, startPosition, oldEndIndex, oldEndPosition, - newEndIndex, newEndPosition - } + newEndIndex, newEndPosition, + }, ]; } function getExtent(text) { - let row = 0 + let row = 0; let index; for (index = 0; index != -1; index = text.indexOf('\n', index)) { - index++ + index++; row++; } return {row, column: text.length - index}; @@ -429,7 +429,7 @@ function assertCursorState(cursor, params) { assert.deepEqual(cursor.startIndex, params.startIndex); assert.deepEqual(cursor.endIndex, params.endIndex); - const node = cursor.currentNode() + const node = cursor.currentNode(); assert.equal(node.type, params.nodeType); assert.equal(node.isNamed(), params.nodeIsNamed); assert.deepEqual(node.startPosition, params.startPosition);