Skip to content

Commit

Permalink
perf(adapter-yaml): optimize syntactic analysis
Browse files Browse the repository at this point in the history
Refs #691
  • Loading branch information
char0n committed Oct 31, 2021
1 parent 731d1f5 commit aa78da6
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 100 deletions.
13 changes: 8 additions & 5 deletions packages/apidom-ast/src/yaml/nodes/YamlKeyValuePair.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import stampit from 'stampit';
import { filter, anyPass, pipe, nth, identical, complement, both } from 'ramda';

import Node from '../../Node';
import YamlStyleModel from './YamlStyle';
Expand All @@ -20,18 +19,22 @@ const YamlKeyValuePair: stampit.Stamp<YamlKeyValuePair> = stampit(Node, YamlStyl
key: {
get() {
// @ts-ignore
return pipe(filter(anyPass([isScalar, isMapping, isSequence])), nth(0))(this.children);
return this.children.filter(
(node: any) => isScalar(node) || isMapping(node) || isSequence(node),
)[0];
},
enumerable: true,
},
value: {
get() {
// @ts-ignore
const { key, children } = this;
const excludeKeyPredicate = complement(identical(key));
const valuePredicate = anyPass([isScalar, isMapping, isSequence, isAlias]);
const excludeKeyPredicate = (node: any) => node !== key;
const valuePredicate = (node: any) =>
isScalar(node) || isMapping(node) || isSequence(node) || isAlias(node);

// @ts-ignore
return pipe(filter(both(excludeKeyPredicate, valuePredicate)), nth(0))(children);
return children.filter((node: any) => excludeKeyPredicate(node) && valuePredicate(node))[0];
},
enumerable: true,
},
Expand Down
3 changes: 1 addition & 2 deletions packages/apidom-ast/src/yaml/nodes/YamlMapping.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import stampit from 'stampit';
import { isArray } from 'ramda-adjunct';

import YamlCollection from './YamlCollection';
import { isKeyValuePair } from './predicates';
Expand All @@ -18,7 +17,7 @@ const YamlMapping: stampit.Stamp<YamlMapping> = stampit(YamlCollection, {
content: {
get(): Array<YamlKeyValuePair> {
// @ts-ignore
return isArray(this.children) ? this.children.filter(isKeyValuePair) : [];
return Array.isArray(this.children) ? this.children.filter(isKeyValuePair) : [];
},
enumerable: true,
},
Expand Down
8 changes: 4 additions & 4 deletions packages/apidom-ast/src/yaml/nodes/YamlSequence.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import stampit from 'stampit';
import { anyPass } from 'ramda';
import { isArray } from 'ramda-adjunct';

import YamlCollection from './YamlCollection';
import YamlMapping from './YamlMapping';
Expand All @@ -23,8 +21,10 @@ const YamlSequence: stampit.Stamp<YamlSequence> = stampit(YamlCollection, {
// @ts-ignore
const { children } = this;

return isArray(children)
? children.filter(anyPass([isSequence, isMapping, isScalar, isAlias]))
return Array.isArray(children)
? children.filter(
(node: any) => isSequence(node) || isMapping(node) || isScalar(node) || isAlias(node),
)
: [];
},
enumerable: true,
Expand Down
7 changes: 4 additions & 3 deletions packages/apidom-ast/src/yaml/nodes/YamlStream.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import stampit from 'stampit';
import { either } from 'ramda';
import { isArray } from 'ramda-adjunct';

import Node from '../../Node';
import YamlDocument from './YamlDocument';
Expand All @@ -21,7 +19,10 @@ const YamlStream: stampit.Stamp<YamlStream> = stampit(Node, {
content: {
get(): Array<YamlDocument | YamlComment> {
// @ts-ignore
return isArray(this.children) ? this.children.filter(either(isDocument, isComment)) : [];
return Array.isArray(this.children)
? // @ts-ignore
this.children.filter((node: any) => isDocument(node) || isComment(node))
: [];
},
enumerable: true,
},
Expand Down
3 changes: 1 addition & 2 deletions packages/apidom-ast/src/yaml/schemas/ScalarTag.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import stampit from 'stampit';
import { isString } from 'ramda-adjunct';

import {
formatFlowPlain,
Expand All @@ -14,7 +13,7 @@ import { YamlNodeKind } from '../nodes/YamlTag';
const ScalarTag = stampit({
methods: {
test(node) {
return node.tag.kind === YamlNodeKind.Scalar && isString(node.content);
return node.tag.kind === YamlNodeKind.Scalar && typeof node.content === 'string';
},

canonicalFormat(node) {
Expand Down
8 changes: 3 additions & 5 deletions packages/apidom-ast/src/yaml/schemas/failsafe/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import stampit from 'stampit';
import { propEq, reject } from 'ramda';
import { isUndefined } from 'ramda-adjunct';

import YamlDirective from '../../nodes/YamlDirective';
import { YamlNodeKind } from '../../nodes/YamlTag';
Expand Down Expand Up @@ -66,7 +64,7 @@ const FailsafeSchema = stampit({
},

overrideTag(tag) {
this.tags = reject(propEq('tag', tag.tag), this.tags);
this.tags = this.tags.filter((itag: any) => itag.tag === tag.tag);
this.tags.push(tag);
return this;
},
Expand All @@ -85,10 +83,10 @@ const FailsafeSchema = stampit({
canonicalNode = ScalarTag().canonicalFormat(node);
}

const tag = this.tags.find(propEq('tag', specificTagName));
const tag = this.tags.find((itag: any) => itag?.tag === specificTagName);

// mechanism for resolving node (tag implementation) not found
if (isUndefined(tag)) {
if (typeof tag === 'undefined') {
throw new Error(`Tag "${specificTagName}" couldn't be resolved`);
}

Expand Down
3 changes: 1 addition & 2 deletions packages/apidom-ast/src/yaml/schemas/json/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import stampit from 'stampit';
import { pathOr } from 'ramda';

import FailsafeSchema from '../failsafe';
import Boolean from './Boolean';
Expand Down Expand Up @@ -35,7 +34,7 @@ const JsonSchema = stampit(FailsafeSchema, {
} else if (node.tag.kind === YamlNodeKind.Scalar) {
// @ts-ignore
const foundTag = this.tags.find((tag) => tag.test(node));
specificTagName = pathOr('?', ['tag'], foundTag);
specificTagName = foundTag?.tag || '?';
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,4 @@
import stampit from 'stampit';
import {
either,
unnest,
flatten,
prop,
propOr,
pathOr,
find,
anyPass,
curry,
propSatisfies,
endsWith,
hasIn,
} from 'ramda';
import { isArray, isFalse, isFunction, isNotUndefined, invokeArgs } from 'ramda-adjunct';
import { SyntaxNode as NodeSyntaxNode } from 'tree-sitter';
import { SyntaxNode as WebSyntaxNode } from 'web-tree-sitter';
import {
Expand Down Expand Up @@ -48,7 +33,7 @@ export const keyMap = {
};

// @ts-ignore
export const isNode = either(isArray, isCSTNode);
export const isNode = (node: any) => Array.isArray(node) || isCSTNode(node);

/* eslint-disable no-param-reassign */

Expand Down Expand Up @@ -89,11 +74,8 @@ const CstVisitor = stampit({
({ previousSibling } = previousSibling);
}

const explicitName = pathOr(
node.type === 'plain_scalar' ? '?' : '!',
['text'],
previousSibling,
);
const explicitName = previousSibling?.text || node.type === 'plain_scalar' ? '?' : '!';

// eslint-disable-next-line no-nested-ternary
const kind = node.type.endsWith('mapping')
? YamlNodeKind.Mapping
Expand Down Expand Up @@ -122,17 +104,18 @@ const CstVisitor = stampit({
/**
* If web-tree-sitter will support keyNode and valueNode this can be further simplified.
*/
const isKind = curry((ending, node) => propSatisfies(endsWith(ending), 'type', node));
const isKind = (ending: string) => (node: any) =>
typeof node?.type === 'string' && node.type.endsWith(ending);
const isScalar = isKind('scalar');
const isMapping = isKind('mapping');
const isSequence = isKind('sequence');

const getFieldFromNode = (fieldName: string, node: SyntaxNode): SyntaxNode | null => {
return hasIn(`${fieldName}Node`, node)
return `${fieldName}Node` in node
? // @ts-ignore
prop(`${fieldName}Node`, node)
: hasIn('childForFieldName', node)
? invokeArgs(['childForFieldName'], [fieldName], node)
node[`${fieldName}Node`]
: 'childForFieldName' in node
? node.childForFieldName?.(fieldName)
: null;
};

Expand All @@ -149,7 +132,9 @@ const CstVisitor = stampit({

// keyNode was not explicitly provided; tag or anchor are provided though
// @ts-ignore
return !keyNode.children.some(anyPass([isScalar, isSequence, isMapping]));
return !keyNode.children.some(
(n: SyntaxNode) => isScalar(n) || isSequence(n) || isMapping(n),
);
};

const isKeyValuePairValueless = (node: SyntaxNode) => {
Expand All @@ -166,7 +151,9 @@ const CstVisitor = stampit({

// valueNode was not explicitly provided; tag or anchor are provided though
// @ts-ignore
return !valueNode.children.some(anyPass([isScalar, isSequence, isMapping]));
return !valueNode.children.some(
(n: SyntaxNode) => isScalar(n) || isSequence(n) || isMapping(n),
);
};

const createKeyValuePairSurrogateKey = (node: SyntaxNode) => {
Expand All @@ -176,22 +163,26 @@ const CstVisitor = stampit({
char: node.startIndex,
});
const keyNode = getFieldFromNode('key', node);
const children = pathOr([], ['children'], keyNode);
const tagNode: any | undefined = find(isKind('tag'), children);
const anchorNode: any | undefined = find(isKind('anchor'), children);
const tag = isNotUndefined(tagNode)
? YamlTag({
explicitName: tagNode.text,
kind: YamlNodeKind.Scalar,
position: toPosition(tagNode),
})
: YamlTag({
explicitName: '?',
kind: YamlNodeKind.Scalar,
});
const anchor = isNotUndefined(anchorNode)
? YamlAnchor({ name: anchorNode.text, position: toPosition(anchorNode) })
: null;
const children = keyNode?.children || [];
// @ts-ignore
const tagNode: any | undefined = children.find(isKind('tag'));
// @ts-ignore
const anchorNode: any | undefined = children.find(isKind('anchor'));
const tag =
typeof tagNode !== 'undefined'
? YamlTag({
explicitName: tagNode.text,
kind: YamlNodeKind.Scalar,
position: toPosition(tagNode),
})
: YamlTag({
explicitName: '?',
kind: YamlNodeKind.Scalar,
});
const anchor =
typeof anchorNode !== 'undefined'
? YamlAnchor({ name: anchorNode.text, position: toPosition(anchorNode) })
: null;

return YamlScalar({
content: '',
Expand All @@ -210,22 +201,26 @@ const CstVisitor = stampit({
char: node.endIndex,
});
const valueNode = getFieldFromNode('value', node);
const children = pathOr([], ['children'], valueNode);
const tagNode: any | undefined = find(isKind('tag'), children);
const anchorNode: any | undefined = find(isKind('anchor'), children);
const tag = isNotUndefined(tagNode)
? YamlTag({
explicitName: tagNode.text,
kind: YamlNodeKind.Scalar,
position: toPosition(tagNode),
})
: YamlTag({
explicitName: '?',
kind: YamlNodeKind.Scalar,
});
const anchor = isNotUndefined(anchorNode)
? YamlAnchor({ name: anchorNode.text, position: toPosition(anchorNode) })
: null;
const children = valueNode?.children || [];
// @ts-ignore
const tagNode: any | undefined = children.find(isKind('tag'));
// @ts-ignore
const anchorNode: any | undefined = children.find(isKind('anchor'));
const tag =
typeof tagNode !== 'undefined'
? YamlTag({
explicitName: tagNode.text,
kind: YamlNodeKind.Scalar,
position: toPosition(tagNode),
})
: YamlTag({
explicitName: '?',
kind: YamlNodeKind.Scalar,
});
const anchor =
typeof anchorNode !== 'undefined'
? YamlAnchor({ name: anchorNode.text, position: toPosition(anchorNode) })
: null;

return YamlScalar({
content: '',
Expand All @@ -247,7 +242,7 @@ const CstVisitor = stampit({
// in `SyntaxNode.isNamed` property. web-tree-sitter has it defined as method
// whether tree-sitter node binding has it defined as a boolean property.
// @ts-ignore
if ((isFunction(node.isNamed) && !node.isNamed()) || isFalse(node.isNamed)) {
if ((typeof node.isNamed === 'function' && !node.isNamed()) || node.isNamed === false) {
const position = toPosition(node);
const value = node.type || node.text;
const isMissing = node.isMissing();
Expand Down Expand Up @@ -276,7 +271,7 @@ const CstVisitor = stampit({
this.yaml_directive = {
enter(node: SyntaxNode) {
const position = toPosition(node);
const version = pathOr(null, ['firstNamedChild', 'text'], node);
const version = node?.firstNamedChild?.text || null;

return YamlDirective({
position,
Expand All @@ -297,8 +292,8 @@ const CstVisitor = stampit({
position,
name: '%TAG',
parameters: {
handle: propOr(null, 'text', tagHandleNode),
prefix: propOr(null, 'text', tagPrefixNode),
handle: tagHandleNode?.text || null,
prefix: tagPrefixNode?.text || null,
},
});

Expand All @@ -317,10 +312,10 @@ const CstVisitor = stampit({

return YamlDirective({
position,
name: propOr(null, 'text', directiveNameNode),
name: directiveNameNode?.text || null,
parameters: {
handle: propOr(null, 'text', directiveParameter1Node),
prefix: propOr(null, 'text', directiveParameter2Node),
handle: directiveParameter1Node?.text || null,
prefix: directiveParameter2Node?.text || null,
},
});
},
Expand All @@ -337,7 +332,7 @@ const CstVisitor = stampit({
});
},
leave(node: YamlDocument) {
node.children = unnest(node.children);
node.children = node.children.flat();
},
};

Expand Down Expand Up @@ -451,7 +446,7 @@ const CstVisitor = stampit({

this.keyValuePair = {
leave(node: YamlKeyValuePair) {
node.children = unnest(node.children);
node.children = node.children.flat();
},
};

Expand Down Expand Up @@ -485,7 +480,7 @@ const CstVisitor = stampit({
const tag = kindNodeToYamlTag(node);
const anchor = kindNodeToYamlAnchor(node);
const sequenceNode = YamlSequence({
children: unnest(node.children),
children: node.children.flat(),
position,
anchor,
tag,
Expand All @@ -499,7 +494,7 @@ const CstVisitor = stampit({

this.sequence = {
leave(node: YamlSequence) {
node.children = flatten(node.children);
node.children = node.children.flat(+Infinity);
},
};

Expand Down
Loading

0 comments on commit aa78da6

Please sign in to comment.