Skip to content

Commit

Permalink
refactor: replace json-ast with tree-sitter
Browse files Browse the repository at this point in the history
This commit replaces underlying json-ast parser with
tree-sitter.

Refs #35
  • Loading branch information
char0n committed Aug 11, 2020
1 parent 43d167c commit fbe723a
Show file tree
Hide file tree
Showing 44 changed files with 267 additions and 183 deletions.
1 change: 1 addition & 0 deletions apidom/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module.exports = {
'import/no-mutable-exports': 0,
'no-labels': 0,
'no-restricted-syntax': 0,
'@typescript-eslint/ban-ts-comment': 'off',
},
plugins: ['@typescript-eslint', 'prettier'],
extends: [
Expand Down
10 changes: 10 additions & 0 deletions apidom/packages/apidom-ast/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions apidom/packages/apidom-ast/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
},
"homepage": "https://github.com/swagger-api/apidom#readme",
"dependencies": {
"ramda": "=0.27.0",
"ramda-adjunct": "=2.26.0",
"stampit": "=4.3.1"
}
}
2 changes: 0 additions & 2 deletions apidom/packages/apidom-ast/src/ParseResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@ const ParseResult: stampit.Stamp<ParseResult> = stampit(Node, {
type: 'parseResult',
},
methods: {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
get rootNode(): unknown {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return head(this.children);
},
Expand Down
17 changes: 17 additions & 0 deletions apidom/packages/apidom-ast/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// JSON AST related exports
export { default as JsonDocument } from './nodes/json/JsonDocument';
export { default as JsonObject } from './nodes/json/JsonObject';
export { default as JsonProperty } from './nodes/json/JsonProperty';
Expand All @@ -11,7 +12,23 @@ export { default as JsonNumber } from './nodes/json/JsonNumber';
export { default as JsonTrue } from './nodes/json/JsonTrue';
export { default as JsonFalse } from './nodes/json/JsonFalse';
export { default as JsonNull } from './nodes/json/JsonNull';
export {
isFalse as isJsonFalse,
isProperty as isJsonProperty,
isStringContent as isJsonStringContent,
isEscapeSequence as isJsonEscapeSequence,
isArray as isJsonArray,
isKey as isJsonKey,
isNull as isJsonNull,
isNumber as isJsonNumber,
isObject as isJsonObject,
isString as isJsonString,
isTrue as isJsonTrue,
} from './nodes/json/predicates';
// generic AST related exports
export { default as Literal } from './Literal';
export { Point, default as Position } from './Position';
export { default as Error } from './Error';
export { default as ParseResult } from './ParseResult';
// AST traversal related exports
export { getVisitFn, BREAK, visit } from './visitor';
1 change: 0 additions & 1 deletion apidom/packages/apidom-ast/src/nodes/json/JsonArray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ const JsonArray: stampit.Stamp<JsonArray> = stampit(Node, {
},
methods: {
get items(): unknown[] {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return this.children.filter(
anyPass([isFalse, isTrue, isNull, isNumber, isString, isArray, isObject]),
Expand Down
2 changes: 0 additions & 2 deletions apidom/packages/apidom-ast/src/nodes/json/JsonDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ const JsonDocument: stampit.Stamp<JsonDocument> = stampit(Node, {
type: 'document',
},
methods: {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
get child(): unknown {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return head(this.children);
},
Expand Down
6 changes: 3 additions & 3 deletions apidom/packages/apidom-ast/src/nodes/json/JsonKey.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import stampit from 'stampit';

import JsonValue from './JsonValue';
import JsonString from './JsonString';

type JsonKey = JsonValue;
type JsonKey = JsonString;

const JsonKey: stampit.Stamp<JsonKey> = stampit(JsonValue, {
const JsonKey: stampit.Stamp<JsonKey> = stampit(JsonString, {
statics: {
type: 'key',
},
Expand Down
1 change: 0 additions & 1 deletion apidom/packages/apidom-ast/src/nodes/json/JsonObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ const JsonObject: stampit.Stamp<JsonObject> = stampit(Node, {
},
methods: {
get properties(): unknown[] {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return this.children.filter(isProperty);
},
Expand Down
24 changes: 16 additions & 8 deletions apidom/packages/apidom-ast/src/nodes/json/JsonProperty.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import stampit from 'stampit';
import { head, last } from 'ramda';
import { anyPass } from 'ramda';

import Node from '../../Node';
import JsonKey from './JsonKey';
import {
isArray,
isFalse,
isKey,
isNull,
isNumber,
isObject,
isString,
isTrue,
} from './predicates';

interface JsonProperty extends Node {
key: JsonKey;
Expand All @@ -14,19 +24,17 @@ const JsonProperty: stampit.Stamp<JsonProperty> = stampit(Node, {
type: 'property',
},
methods: {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
get key(): unknown {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
get key(): JsonKey {
// @ts-ignore
return head(this.children);
return this.children.find(isKey);
},
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
get value(): unknown {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return last(this.children);
return this.children.find(
anyPass([isFalse, isTrue, isNull, isNumber, isString, isArray, isObject]),
);
},
},
});
Expand Down
1 change: 0 additions & 1 deletion apidom/packages/apidom-ast/src/nodes/json/JsonString.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ const JsonString: stampit.Stamp<JsonString> = stampit(Node, {
get value(): string {
return (
this.children
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
.filter(either(isStringContent, isEscapeSequence))
.reduce(
Expand Down
2 changes: 2 additions & 0 deletions apidom/packages/apidom-ast/src/nodes/json/predicates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ export const isStringContent = isNodeType('stringContent');
export const isEscapeSequence = isNodeType('escapeSequence');

export const isProperty = isNodeType('property');

export const isKey = isNodeType('key');
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { nodeTypes } from 'json-ast';
import { pathSatisfies } from 'ramda';
import { isFunction, isString, isNotNil } from 'ramda-adjunct';

// getVisitFn :: (Visitor, String, Boolean) -> Function
const getVisitFn = (visitor, type, isLeaving) => {
// @ts-ignore
export const getVisitFn = (visitor, type: string, isLeaving: boolean) => {
const typeVisitor = visitor[type];

if (isNotNil(typeVisitor)) {
Expand Down Expand Up @@ -59,15 +59,15 @@ const isNode = pathSatisfies(isString, ['type']);
* // @return
* // undefined: no action
* // false: skip visiting this node
* // visitor.BREAK: stop visiting altogether
* // BREAK: stop visiting altogether
* // null: delete this node
* // any value: replace this node with the returned value
* },
* leave(node, key, parent, path, ancestors) {
* // @return
* // undefined: no action
* // false: no action
* // visitor.BREAK: stop visiting altogether
* // BREAK: stop visiting altogether
* // null: delete this node
* // any value: replace this node with the returned value
* }
Expand Down Expand Up @@ -129,13 +129,15 @@ const isNode = pathSatisfies(isString, ['type']);
* @sig visit :: (Node, Visitor, Options)
* @sig Options = { keyMap: Object, state: Object }
*/
export const visit = (root, visitor, { keyMap = null, state = {} } = {}) => {
const visitorKeys = keyMap || {
[nodeTypes.DOCUMENT]: ['comments', 'child'],
[nodeTypes.OBJECT]: ['comments', 'properties'],
[nodeTypes.PROPERTY]: ['key', 'value'],
[nodeTypes.ARRAY]: ['comments', 'items'],
};

export const visit = (
// @ts-ignore
root,
// @ts-ignore
visitor,
{ keyMap = null, state = {}, breakSymbol = BREAK, visitFnGetter = getVisitFn } = {},
) => {
const visitorKeys = keyMap || {};

let stack;
let inArray = Array.isArray(root);
Expand All @@ -144,6 +146,7 @@ export const visit = (root, visitor, { keyMap = null, state = {} } = {}) => {
let parent;
let edits = [];
const path = [];
// @ts-ignore
const ancestors = [];
let newRoot = root;

Expand All @@ -156,9 +159,11 @@ export const visit = (root, visitor, { keyMap = null, state = {} } = {}) => {
if (isLeaving) {
key = ancestors.length === 0 ? undefined : path.pop();
node = parent;
// @ts-ignore
parent = ancestors.pop();
if (isEdited) {
if (inArray) {
// @ts-ignore
node = node.slice();
} else {
// creating clone
Expand All @@ -181,8 +186,11 @@ export const visit = (root, visitor, { keyMap = null, state = {} } = {}) => {
}
index = stack.index;
keys = stack.keys;
// @ts-ignore
edits = stack.edits;
// @ts-ignore
inArray = stack.inArray;
// @ts-ignore
stack = stack.prev;
} else {
key = parent ? (inArray ? index : keys[index]) : undefined;
Expand All @@ -200,7 +208,7 @@ export const visit = (root, visitor, { keyMap = null, state = {} } = {}) => {
if (!isNode(node)) {
throw new Error(`Invalid AST Node: ${JSON.stringify(node)}`);
}
const visitFn = getVisitFn(visitor, node.type, isLeaving);
const visitFn = visitFnGetter(visitor, node.type, isLeaving);
if (visitFn) {
// assign state
for (const [stateKey, stateValue] of Object.entries(state)) {
Expand All @@ -209,7 +217,7 @@ export const visit = (root, visitor, { keyMap = null, state = {} } = {}) => {

result = visitFn.call(visitor, node, key, parent, path, ancestors);

if (result === BREAK) {
if (result === breakSymbol) {
break;
}

Expand Down Expand Up @@ -239,6 +247,7 @@ export const visit = (root, visitor, { keyMap = null, state = {} } = {}) => {
if (!isLeaving) {
stack = { inArray, index, keys, edits, prev: stack };
inArray = Array.isArray(node);
// @ts-ignore
keys = inArray ? node : visitorKeys[node.type] || [];
index = -1;
edits = [];
Expand All @@ -255,4 +264,5 @@ export const visit = (root, visitor, { keyMap = null, state = {} } = {}) => {

return newRoot;
};

/* eslint-enable */
18 changes: 13 additions & 5 deletions apidom/packages/apidom-parser-adapter-openapi3-1/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
"apidom": "file:../apidom",
"apidom-ast": "file:../apidom-ast",
"apidom-ns-openapi3-1": "file:../apidom-ns-openapi3-1",
"json-ast": "=2.1.7",
"ramda": "=0.27.0",
"ramda-adjunct": "=2.26.0",
"stampit": "=4.3.1",
Expand Down
Loading

0 comments on commit fbe723a

Please sign in to comment.