Skip to content

perf: flatten sourceMap to improve memory usage #4964

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
36 changes: 33 additions & 3 deletions packages/apidom-ast/src/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ export interface NodeOptions {
readonly children?: unknown[];
readonly position?: Position;
readonly isMissing?: boolean;
readonly startPositionRow?: number;
readonly startPositionColumn?: number;
readonly startIndex?: number;
readonly endPositionRow?: number;
readonly endPositionColumn?: number;
readonly endIndex?: number;
}

/**
Expand All @@ -21,13 +27,37 @@ class Node {

public children: unknown[];

public position?: Position;
public startPositionRow?: number;

constructor({ children = [], position, isMissing = false }: NodeOptions = {}) {
public startPositionColumn?: number;

public startIndex?: number;

public endPositionRow?: number;

public endPositionColumn?: number;

public endIndex?: number;

constructor({
children = [],
isMissing = false,
startPositionRow,
startPositionColumn,
startIndex,
endPositionRow,
endPositionColumn,
endIndex,
}: NodeOptions = {}) {
this.type = (this.constructor as typeof Node).type;
this.isMissing = isMissing;
this.children = children;
this.position = position;
this.startPositionRow = startPositionRow;
this.startPositionColumn = startPositionColumn;
this.startIndex = startIndex;
this.endPositionRow = endPositionRow;
this.endPositionColumn = endPositionColumn;
this.endIndex = endIndex;
}

// creates shallow clone of node
Expand Down
2 changes: 1 addition & 1 deletion packages/apidom-ast/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export type { PointOptions, PositionOptions } from './Position.ts';
export { default as Error } from './Error.ts';
export type { ErrorOptions } from './Error.ts';
export { default as ParseResult } from './ParseResult.ts';
export { isParseResult, isLiteral, isPoint, isPosition } from './predicates.ts';
export { isParseResult, isLiteral } from './predicates.ts';
// AST traversal related exports
export {
BREAK,
Expand Down
11 changes: 0 additions & 11 deletions packages/apidom-ast/src/predicates.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type Literal from './Literal.ts';
import Position, { Point } from './Position.ts';
import ParseResult from './ParseResult.ts';

/**
Expand All @@ -13,16 +12,6 @@ export const isNodeType = (type: string, node: unknown): boolean =>
*/
export const isLiteral = (node: unknown): node is Literal => isNodeType('literal', node);

/**
* @public
*/
export const isPosition = (node: unknown): node is Position => isNodeType('position', node);

/**
* @public
*/
export const isPoint = (node: unknown): node is Point => isNodeType('point', node);

/**
* @public
*/
Expand Down
27 changes: 23 additions & 4 deletions packages/apidom-ast/src/yaml/errors/YamlTagError.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { ApiDOMErrorOptions } from '@swagger-api/apidom-error';

import YamlSchemaError from './YamlSchemaError.ts';
import Position from '../../Position.ts';
import Node from '../../Node.ts';

/**
Expand All @@ -11,7 +10,12 @@ export interface YamlTagErrorOptions<T extends Node = Node> extends ApiDOMErrorO
readonly specificTagName: string;
readonly explicitTagName: string;
readonly tagKind: string;
readonly tagPosition?: Position;
readonly tagStartPositionRow?: number;
readonly tagStartPositionColumn?: number;
readonly tagStartPositionIndex?: number;
readonly tagEndPositionRow?: number;
readonly tagEndPositionColumn?: number;
readonly tagEndPositionIndex?: number;
readonly nodeCanonicalContent?: string;
readonly node?: T;
}
Expand All @@ -26,7 +30,17 @@ class YamlTagError extends YamlSchemaError {

public readonly tagKind!: string;

public readonly tagPosition?: Position;
public readonly tagStartPositionRow?: number;

public readonly tagStartPositionColumn?: number;

public readonly tagStartPositionIndex?: number;

public readonly tagEndPositionRow?: number;

public readonly tagEndPositionColumn?: number;

public readonly tagEndPositionIndex?: number;

public readonly nodeCanonicalContent?: string;

Expand All @@ -39,7 +53,12 @@ class YamlTagError extends YamlSchemaError {
this.specificTagName = structuredOptions.specificTagName;
this.explicitTagName = structuredOptions.explicitTagName;
this.tagKind = structuredOptions.tagKind;
this.tagPosition = structuredOptions.tagPosition;
this.tagStartPositionRow = structuredOptions.tagStartPositionRow;
this.tagStartPositionColumn = structuredOptions.tagStartPositionColumn;
this.tagStartPositionIndex = structuredOptions.tagStartPositionIndex;
this.tagEndPositionRow = structuredOptions.tagEndPositionRow;
this.tagEndPositionColumn = structuredOptions.tagEndPositionColumn;
this.tagEndPositionIndex = structuredOptions.tagEndPositionIndex;
this.nodeCanonicalContent = structuredOptions.nodeCanonicalContent;
this.node = structuredOptions.node;
}
Expand Down
16 changes: 12 additions & 4 deletions packages/apidom-ast/src/yaml/schemas/failsafe/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { clone } from 'ramda';

import YamlTagError from '../../errors/YamlTagError.ts';
import YamlDirective from '../../nodes/YamlDirective.ts';
import { YamlNodeKind } from '../../nodes/YamlTag.ts';
Expand Down Expand Up @@ -95,7 +93,12 @@ class FailsafeSchema {
specificTagName,
explicitTagName: node.tag.explicitName,
tagKind: node.tag.kind,
tagPosition: clone(node.tag.position),
tagStartPositionRow: node.tag.startPositionRow,
tagStartPositionColumn: node.tag.startPositionColumn,
tagStartPositionIndex: node.tag.startIndex,
tagEndPositionRow: node.tag.endPositionRow,
tagEndPositionColumn: node.tag.endPositionColumn,
tagEndPositionIndex: node.tag.endIndex,
node: node.clone(),
});
}
Expand All @@ -106,7 +109,12 @@ class FailsafeSchema {
specificTagName,
explicitTagName: node.tag.explicitName,
tagKind: node.tag.kind,
tagPosition: clone(node.tag.position),
tagStartPositionRow: node.tag.startPositionRow,
tagStartPositionColumn: node.tag.startPositionColumn,
tagStartPositionIndex: node.tag.startIndex,
tagEndPositionRow: node.tag.endPositionRow,
tagEndPositionColumn: node.tag.endPositionColumn,
tagEndPositionIndex: node.tag.endIndex,
nodeCanonicalContent: canonicalNode.content,
node: node.clone(),
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { Element, Meta, Attributes, AnnotationElement } from '@swagger-api/apidom-core';
import {
Element,
Meta,
Attributes,
AnnotationElement,
assignSourceMap,
} from '@swagger-api/apidom-core';
import { createToolbox as createToolboxOpenAPI31 } from '@swagger-api/apidom-ns-openapi-3-1';

const createToolbox = () => {
const openAPI31Toolbox = createToolboxOpenAPI31();

const copySourceMap = <T extends Element, U extends Element>(from: T, to: U): void => {
if (openAPI31Toolbox.predicates.hasElementSourceMap(from)) {
to.meta.set('sourceMap', from.meta.get('sourceMap'));
assignSourceMap(to, from);
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { mediaTypes as openAPI31MediaTypes } from '@swagger-api/apidom-parser-adapter-openapi-json-3-1';
import { mediaTypes as openAPI30MediaTypes } from '@swagger-api/apidom-parser-adapter-openapi-json-3-0';
import { AnnotationElement, includesClasses, toJSON, toValue } from '@swagger-api/apidom-core';
import { AnnotationElement, includesClasses, toJSON } from '@swagger-api/apidom-core';
import { assert, expect } from 'chai';

import convert from '../../../../../src/index.ts';
Expand Down Expand Up @@ -73,20 +73,22 @@ describe('converter', function () {
const annotation: AnnotationElement = annotations.find((a: AnnotationElement) =>
a.code?.equals('security-requirements-empty-roles'),
);
const sourceMap = annotation.meta.get('sourceMap');
const { positionStart, positionEnd } = sourceMap;
const [startRow, startColumn, startChar] = toValue(positionStart);
const [endRow, endColumn, endChar] = toValue(positionEnd);
const {
startPositionRow,
startPositionColumn,
startIndex,
endPositionRow,
endPositionColumn,
endIndex,
} = annotation;

assert.isDefined(sourceMap);
assert.strictEqual(startPositionRow, 15);
assert.strictEqual(startPositionColumn, 29);
assert.strictEqual(startIndex, 299);

assert.strictEqual(startRow, 15);
assert.strictEqual(startColumn, 29);
assert.strictEqual(startChar, 299);

assert.strictEqual(endRow, 18);
assert.strictEqual(endColumn, 13);
assert.strictEqual(endChar, 358);
assert.strictEqual(endPositionRow, 18);
assert.strictEqual(endPositionColumn, 13);
assert.strictEqual(endIndex, 358);
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { mediaTypes as openAPI31MediaTypes } from '@swagger-api/apidom-parser-adapter-openapi-json-3-1';
import { mediaTypes as openAPI30MediaTypes } from '@swagger-api/apidom-parser-adapter-openapi-json-3-0';
import { AnnotationElement, includesClasses, toJSON, toValue } from '@swagger-api/apidom-core';
import { AnnotationElement, includesClasses, toJSON } from '@swagger-api/apidom-core';
import { assert, expect } from 'chai';

import convert from '../../../../../src/index.ts';
Expand Down Expand Up @@ -61,20 +61,22 @@ describe('converter', function () {
const annotation: AnnotationElement = annotations.find((a: AnnotationElement) =>
a.code?.equals('mutualTLS'),
);
const sourceMap = annotation.meta.get('sourceMap');
const { positionStart, positionEnd } = sourceMap;
const [startRow, startColumn, startChar] = toValue(positionStart);
const [endRow, endColumn, endChar] = toValue(positionEnd);
const {
startPositionRow,
startPositionColumn,
startIndex,
endPositionRow,
endPositionColumn,
endIndex,
} = annotation;

assert.isDefined(sourceMap);
assert.strictEqual(startPositionRow, 9);
assert.strictEqual(startPositionColumn, 32);
assert.strictEqual(startIndex, 188);

assert.strictEqual(startRow, 9);
assert.strictEqual(startColumn, 32);
assert.strictEqual(startChar, 188);

assert.strictEqual(endRow, 12);
assert.strictEqual(endColumn, 13);
assert.strictEqual(endChar, 247);
assert.strictEqual(endPositionRow, 12);
assert.strictEqual(endPositionColumn, 13);
assert.strictEqual(endIndex, 247);
});

specify(
Expand Down
7 changes: 6 additions & 1 deletion packages/apidom-core/src/clone/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { ArraySlice, ObjectSlice, KeyValuePair, Element } from 'minim';

import { isElement } from '../predicates/index.ts';
import { hasElementSourceMap, isElement } from '../predicates/index.ts';
import DeepCloneError from './errors/DeepCloneError.ts';
import ShallowCloneError from './errors/ShallowCloneError.ts';
import { assignSourceMap } from '../util.ts';

/**
* @public
Expand Down Expand Up @@ -123,6 +124,10 @@ const cloneShallowElement = <T extends Element>(element: T): T => {

copy.element = element.element;

if (hasElementSourceMap(element)) {
assignSourceMap(copy, element);
}

if (element.meta.length > 0) {
copy._meta = cloneDeep(element.meta);
}
Expand Down
56 changes: 0 additions & 56 deletions packages/apidom-core/src/elements/SourceMap.ts

This file was deleted.

5 changes: 1 addition & 4 deletions packages/apidom-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export { default as MediaTypes } from './media-types.ts';

export { Element, MemberElement, KeyValuePair, ObjectSlice, ArraySlice, refract } from 'minim';
export type { NamespacePluginOptions, Attributes, Meta } from 'minim';
export type { PositionRange, Position } from './elements/SourceMap.ts';
export { default as namespace, Namespace, createNamespace } from './namespace.ts';

export {
Expand All @@ -28,7 +27,6 @@ export {
AnnotationElement,
CommentElement,
ParseResultElement,
SourceMapElement,
} from './refractor/registration.ts';

export type { default as createToolbox, Toolbox, basePredicates } from './refractor/toolbox.ts';
Expand All @@ -46,7 +44,6 @@ export {
isRefElement,
isAnnotationElement,
isParseResultElement,
isSourceMapElement,
isPrimitiveElement,
hasElementSourceMap,
includesSymbols,
Expand Down Expand Up @@ -83,7 +80,7 @@ export type { Callback, TraverseOptions } from './traversal/traverse.ts';

export { transclude, default as Transcluder } from './transcluder/index.ts';

export { dereference } from './util.ts';
export { dereference, assignSourceMap } from './util.ts';

export { cloneShallow, cloneDeep } from './clone/index.ts';
export { default as CloneError } from './clone/errors/CloneError.ts';
Expand Down
Loading