Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(adapter-yaml): optimize syntactic analysis #846

Merged
merged 1 commit into from
Oct 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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