diff --git a/package-lock.json b/package-lock.json index eb2acc7..afdbe22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1428,6 +1428,11 @@ } } }, + "@newdash/newdash": { + "version": "5.10.0", + "resolved": "https://registry.npm.taobao.org/@newdash/newdash/download/@newdash/newdash-5.10.0.tgz", + "integrity": "sha1-Mbf5Vqs1NJoTWeAwSsLM0dx1ZlU=" + }, "@sinonjs/commons": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.0.tgz", diff --git a/package.json b/package.json index 68dfc6c..f03de32 100644 --- a/package.json +++ b/package.json @@ -38,5 +38,8 @@ "typedoc-default-themes": "^0.5.0", "typedoc-plugin-external-module-name": "^1.1.1", "typescript": "^3.9.6" + }, + "dependencies": { + "@newdash/newdash": "^5.10.0" } } diff --git a/src/utils.ts b/src/utils.ts index b227bfc..7e0a648 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,3 +1,7 @@ +import { Token, TokenType } from './lexer'; +import { forEach, isArray } from '@newdash/newdash'; +import { isPlainObject } from '@newdash/newdash/isPlainObject'; + export type SourceArray = number[] | Uint16Array; export function stringify(value: SourceArray, index: number, next: number): string { @@ -31,4 +35,48 @@ export function required(value: SourceArray, index: number, comparer: Function, return i >= (min || 0) && i <= max ? index + i : 0; } +export type Traverser = { [key in TokenType]?: (token: Token) => void } + +export function createTraverser(traverser: Traverser) { + return function t(node: Token | Array | Object): void { + + if (node instanceof Token) { + if (node.type in traverser) { + traverser[node.type](node); + } + } + + if (isPlainObject(node) || isArray(node) || node instanceof Token) { + // @ts-ignore + forEach(node, (item) => { + t(item); + }); + } + + + }; +} + +/** + * find one node by type + * @param node + * @param type + */ +export function findOne(node: Token, type: TokenType): Token { + let rt: Token; + createTraverser({ [type]: (v: Token) => { rt = v; } })(node); + return rt; +} + +/** + * find all nodes by type + * @param node + * @param type + */ +export function findAll(node: Token, type: TokenType): Array { + const rt: Array = []; + createTraverser({ [type]: (v: Token) => { rt.push(v); } })(node); + return rt; +} + export default { stringify, is, equals, required }; diff --git a/test/query.spec.ts b/test/query.spec.ts index cfbf017..ace6768 100644 --- a/test/query.spec.ts +++ b/test/query.spec.ts @@ -1,4 +1,6 @@ import { Parser } from '../src/parser'; +import { findOne } from '../src/utils'; +import { TokenType } from '../src/lexer'; describe('Query Test Suite', () => { @@ -58,12 +60,9 @@ describe('Query Test Suite', () => { it('should parse $count', () => { - parser.query('$count=true'); + const ast = parser.query('$count=true'); + const node = findOne(ast, TokenType.InlineCount); + expect(node).not.toBeUndefined(); }); - // it('should parser $query', () => { - // parser.query('/Category/$query'); - // }); - - });