From a99ebbc9eee99f7dc9b22c3911d7b9da39a9a89f Mon Sep 17 00:00:00 2001 From: Vladimir Gorej Date: Fri, 25 Sep 2020 15:36:46 +0200 Subject: [PATCH] feat(AST): introduce YAML AST Refs #1 --- apidom/packages/apidom-ast/package.json | 2 +- .../apidom-ast/src/nodes/json/JsonArray.ts | 2 +- .../apidom-ast/src/nodes/json/JsonDocument.ts | 2 +- .../apidom-ast/src/nodes/json/JsonObject.ts | 3 +- .../apidom-ast/src/nodes/json/JsonProperty.ts | 2 +- .../apidom-ast/src/nodes/json/JsonString.ts | 2 +- .../src/nodes/yaml/YamlBlockScalar.ts | 51 +++++++++++++++++++ .../apidom-ast/src/nodes/yaml/YamlComment.ts | 21 ++++++++ .../apidom-ast/src/nodes/yaml/YamlDocument.ts | 23 +++++++++ .../src/nodes/yaml/YamlDoubleQuoteScalar.ts | 13 +++++ .../apidom-ast/src/nodes/yaml/YamlMap.ts | 23 +++++++++ .../apidom-ast/src/nodes/yaml/YamlNode.ts | 18 +++++++ .../apidom-ast/src/nodes/yaml/YamlPair.ts | 31 +++++++++++ .../src/nodes/yaml/YamlPlainScalar.ts | 13 +++++ .../apidom-ast/src/nodes/yaml/YamlScalar.ts | 21 ++++++++ .../apidom-ast/src/nodes/yaml/YamlSeq.ts | 21 ++++++++ .../src/nodes/yaml/YamlSingleQuoteScalar.ts | 13 +++++ .../apidom-ast/src/nodes/yaml/YamlStream.ts | 13 +++++ .../apidom-ast/src/nodes/yaml/YamlTag.ts | 21 ++++++++ .../apidom-ast/src/nodes/yaml/predicates.ts | 29 +++++++++++ .../src/parser/visitors/generics/index.ts | 2 +- .../src/parser/visitors/generics/index.ts | 2 +- 22 files changed, 320 insertions(+), 8 deletions(-) create mode 100644 apidom/packages/apidom-ast/src/nodes/yaml/YamlBlockScalar.ts create mode 100644 apidom/packages/apidom-ast/src/nodes/yaml/YamlComment.ts create mode 100644 apidom/packages/apidom-ast/src/nodes/yaml/YamlDocument.ts create mode 100644 apidom/packages/apidom-ast/src/nodes/yaml/YamlDoubleQuoteScalar.ts create mode 100644 apidom/packages/apidom-ast/src/nodes/yaml/YamlMap.ts create mode 100644 apidom/packages/apidom-ast/src/nodes/yaml/YamlNode.ts create mode 100644 apidom/packages/apidom-ast/src/nodes/yaml/YamlPair.ts create mode 100644 apidom/packages/apidom-ast/src/nodes/yaml/YamlPlainScalar.ts create mode 100644 apidom/packages/apidom-ast/src/nodes/yaml/YamlScalar.ts create mode 100644 apidom/packages/apidom-ast/src/nodes/yaml/YamlSeq.ts create mode 100644 apidom/packages/apidom-ast/src/nodes/yaml/YamlSingleQuoteScalar.ts create mode 100644 apidom/packages/apidom-ast/src/nodes/yaml/YamlStream.ts create mode 100644 apidom/packages/apidom-ast/src/nodes/yaml/YamlTag.ts create mode 100644 apidom/packages/apidom-ast/src/nodes/yaml/predicates.ts diff --git a/apidom/packages/apidom-ast/package.json b/apidom/packages/apidom-ast/package.json index 9f4f5707ab..c54f73bf04 100644 --- a/apidom/packages/apidom-ast/package.json +++ b/apidom/packages/apidom-ast/package.json @@ -40,7 +40,7 @@ "stampit": "=4.3.1" }, "devDependencies": { - "tree-sitter": "=0.16.2", + "tree-sitter": "=0.17.0", "tree-sitter-json": "=0.16.0" } } diff --git a/apidom/packages/apidom-ast/src/nodes/json/JsonArray.ts b/apidom/packages/apidom-ast/src/nodes/json/JsonArray.ts index 6bf218826c..bd8a77a2be 100644 --- a/apidom/packages/apidom-ast/src/nodes/json/JsonArray.ts +++ b/apidom/packages/apidom-ast/src/nodes/json/JsonArray.ts @@ -4,7 +4,7 @@ import { anyPass } from 'ramda'; import JsonNode from './JsonNode'; import { isFalse, isTrue, isNull, isNumber, isString, isArray, isObject } from './predicates'; -type JsonArray = Node; +type JsonArray = JsonNode; const JsonArray: stampit.Stamp = stampit(JsonNode, { statics: { diff --git a/apidom/packages/apidom-ast/src/nodes/json/JsonDocument.ts b/apidom/packages/apidom-ast/src/nodes/json/JsonDocument.ts index 315b4607ce..35bcb7f1f4 100644 --- a/apidom/packages/apidom-ast/src/nodes/json/JsonDocument.ts +++ b/apidom/packages/apidom-ast/src/nodes/json/JsonDocument.ts @@ -3,7 +3,7 @@ import { head } from 'ramda'; import JsonNode from './JsonNode'; -interface JsonDocument extends Node { +interface JsonDocument extends JsonNode { child: unknown | null; } diff --git a/apidom/packages/apidom-ast/src/nodes/json/JsonObject.ts b/apidom/packages/apidom-ast/src/nodes/json/JsonObject.ts index 04d925aed5..7a445ade90 100644 --- a/apidom/packages/apidom-ast/src/nodes/json/JsonObject.ts +++ b/apidom/packages/apidom-ast/src/nodes/json/JsonObject.ts @@ -1,6 +1,7 @@ import stampit from 'stampit'; import JsonNode from './JsonNode'; +import JsonProperty from './JsonProperty'; import { isProperty } from './predicates'; type JsonObject = JsonNode; @@ -10,7 +11,7 @@ const JsonObject: stampit.Stamp = stampit(JsonNode, { type: 'object', }, methods: { - get properties(): unknown[] { + get properties(): Array { // @ts-ignore return this.children.filter(isProperty); }, diff --git a/apidom/packages/apidom-ast/src/nodes/json/JsonProperty.ts b/apidom/packages/apidom-ast/src/nodes/json/JsonProperty.ts index 010a8ad188..fcd1269d55 100644 --- a/apidom/packages/apidom-ast/src/nodes/json/JsonProperty.ts +++ b/apidom/packages/apidom-ast/src/nodes/json/JsonProperty.ts @@ -14,7 +14,7 @@ import { isTrue, } from './predicates'; -interface JsonProperty extends Node { +interface JsonProperty extends JsonNode { key: JsonKey; value: unknown; } diff --git a/apidom/packages/apidom-ast/src/nodes/json/JsonString.ts b/apidom/packages/apidom-ast/src/nodes/json/JsonString.ts index f1870d6a3a..73d910805f 100644 --- a/apidom/packages/apidom-ast/src/nodes/json/JsonString.ts +++ b/apidom/packages/apidom-ast/src/nodes/json/JsonString.ts @@ -6,7 +6,7 @@ import JsonStringContent from './JsonStringContent'; import JsonEscapeSequence from './JsonEscapeSequence'; import { isEscapeSequence, isStringContent } from './predicates'; -interface JsonString extends Node { +interface JsonString extends JsonNode { value: string; } diff --git a/apidom/packages/apidom-ast/src/nodes/yaml/YamlBlockScalar.ts b/apidom/packages/apidom-ast/src/nodes/yaml/YamlBlockScalar.ts new file mode 100644 index 0000000000..b0e4e1bda5 --- /dev/null +++ b/apidom/packages/apidom-ast/src/nodes/yaml/YamlBlockScalar.ts @@ -0,0 +1,51 @@ +import stampit from 'stampit'; +import { test } from 'ramda'; +import { isString } from 'ramda-adjunct'; + +import YamlScalar from './YamlScalar'; + +enum BlockStyleIndicator { + LITERAL = 'LITERAL', + FOLDED = 'FOLDED', +} + +enum BlockChompingIndicator { + CLIP = 'CLIP', + STRIP = 'STRIP', + KEEP = 'KEEP', +} + +interface YamlBlockScalar extends YamlScalar { + readonly style: BlockStyleIndicator; + readonly chomping: BlockChompingIndicator; +} + +const YamlBlockScalar: stampit.Stamp = stampit(YamlScalar, { + statics: { + type: 'blockScalar', + }, + props: { + style: BlockStyleIndicator.LITERAL, + chomping: BlockChompingIndicator.CLIP, + }, + methods: { + get style(): BlockStyleIndicator { + return isString(this.value) && test(/^|/, this.value) + ? BlockStyleIndicator.LITERAL + : BlockStyleIndicator.FOLDED; + }, + get chomping(): BlockChompingIndicator { + /* eslint-disable no-nested-ternary */ + return !isString(this.value) + ? BlockChompingIndicator.CLIP + : test(/^(>|\|)\+/, this.value) + ? BlockChompingIndicator.KEEP + : test(/^(>|\|)-/, this.value) + ? BlockChompingIndicator.STRIP + : BlockChompingIndicator.CLIP; + /* eslint-enable */ + }, + }, +}); + +export default YamlBlockScalar; diff --git a/apidom/packages/apidom-ast/src/nodes/yaml/YamlComment.ts b/apidom/packages/apidom-ast/src/nodes/yaml/YamlComment.ts new file mode 100644 index 0000000000..760db335c3 --- /dev/null +++ b/apidom/packages/apidom-ast/src/nodes/yaml/YamlComment.ts @@ -0,0 +1,21 @@ +import stampit from 'stampit'; + +import YamlNode from './YamlNode'; + +interface YamlComment extends YamlNode { + value: string | null; +} + +const YamlComment: stampit.Stamp = stampit(YamlNode, { + statics: { + type: 'comment', + }, + props: { + value: null, + }, + init({ value = null } = {}) { + this.value = value; + }, +}); + +export default YamlComment; diff --git a/apidom/packages/apidom-ast/src/nodes/yaml/YamlDocument.ts b/apidom/packages/apidom-ast/src/nodes/yaml/YamlDocument.ts new file mode 100644 index 0000000000..ae96e2ce1e --- /dev/null +++ b/apidom/packages/apidom-ast/src/nodes/yaml/YamlDocument.ts @@ -0,0 +1,23 @@ +import stampit from 'stampit'; +import { head } from 'ramda'; + +import YamlNode from './YamlNode'; + +interface YamlDocument extends YamlNode { + child: unknown | null; +} + +const YamlDocument: stampit.Stamp = stampit(YamlNode, { + statics: { + type: 'document', + }, + methods: { + // @ts-ignore + get child(): unknown { + // @ts-ignore + return head(this.children); + }, + }, +}); + +export default YamlDocument; diff --git a/apidom/packages/apidom-ast/src/nodes/yaml/YamlDoubleQuoteScalar.ts b/apidom/packages/apidom-ast/src/nodes/yaml/YamlDoubleQuoteScalar.ts new file mode 100644 index 0000000000..d4f0e470de --- /dev/null +++ b/apidom/packages/apidom-ast/src/nodes/yaml/YamlDoubleQuoteScalar.ts @@ -0,0 +1,13 @@ +import stampit from 'stampit'; + +import YamlScalar from './YamlScalar'; + +type YamlDoubleQuoteScalar = YamlScalar; + +const YamlDoubleQuoteScalar: stampit.Stamp = stampit(YamlScalar, { + statics: { + type: 'doubleQuoteScalar', + }, +}); + +export default YamlDoubleQuoteScalar; diff --git a/apidom/packages/apidom-ast/src/nodes/yaml/YamlMap.ts b/apidom/packages/apidom-ast/src/nodes/yaml/YamlMap.ts new file mode 100644 index 0000000000..4063e97a7d --- /dev/null +++ b/apidom/packages/apidom-ast/src/nodes/yaml/YamlMap.ts @@ -0,0 +1,23 @@ +import stampit from 'stampit'; + +import YamlNode from './YamlNode'; +import YamlPair from './YamlPair'; +import { isPair } from './predicates'; + +interface YamlMap extends YamlNode { + readonly entries: Array; +} + +const YamlStream: stampit.Stamp = stampit(YamlNode, { + statics: { + type: 'map', + }, + methods: { + get entries(): Array { + // @ts-ignore + return this.children.filter(isPair); + }, + }, +}); + +export default YamlStream; diff --git a/apidom/packages/apidom-ast/src/nodes/yaml/YamlNode.ts b/apidom/packages/apidom-ast/src/nodes/yaml/YamlNode.ts new file mode 100644 index 0000000000..2deb30ea58 --- /dev/null +++ b/apidom/packages/apidom-ast/src/nodes/yaml/YamlNode.ts @@ -0,0 +1,18 @@ +import stampit from 'stampit'; + +import Node from '../../Node'; + +interface YamlNode extends Node { + tag: unknown | null; +} + +const YamlNode: stampit.Stamp = stampit(Node, { + props: { + tag: null, + }, + init({ tag = null } = {}) { + this.tag = tag; + }, +}); + +export default YamlNode; diff --git a/apidom/packages/apidom-ast/src/nodes/yaml/YamlPair.ts b/apidom/packages/apidom-ast/src/nodes/yaml/YamlPair.ts new file mode 100644 index 0000000000..c89ff00fcb --- /dev/null +++ b/apidom/packages/apidom-ast/src/nodes/yaml/YamlPair.ts @@ -0,0 +1,31 @@ +import stampit from 'stampit'; +import { anyPass } from 'ramda'; + +import YamlNode from './YamlNode'; +import { isScalar, isMap, isSeq } from './predicates'; +import YamlScalar from './YamlScalar'; + +interface YamlPair extends YamlNode { + readonly key: unknown; + readonly value: unknown; +} + +const YamlPair: stampit.Stamp = stampit(YamlNode, { + statics: { + type: 'pair', + }, + methods: { + // @ts-ignore + get key(): YamlScalar { + // @ts-ignore + return this.children.find(isScalar); + }, + // @ts-ignore + get value(): unknown { + // @ts-ignore + return this.children.find(anyPass([isMap, isSeq, isScalar])); + }, + }, +}); + +export default YamlPair; diff --git a/apidom/packages/apidom-ast/src/nodes/yaml/YamlPlainScalar.ts b/apidom/packages/apidom-ast/src/nodes/yaml/YamlPlainScalar.ts new file mode 100644 index 0000000000..3855e18c5c --- /dev/null +++ b/apidom/packages/apidom-ast/src/nodes/yaml/YamlPlainScalar.ts @@ -0,0 +1,13 @@ +import stampit from 'stampit'; + +import YamlScalar from './YamlScalar'; + +type YamlPlainScalar = YamlScalar; + +const YamlPlainScalar: stampit.Stamp = stampit(YamlScalar, { + statics: { + type: 'plainScalar', + }, +}); + +export default YamlPlainScalar; diff --git a/apidom/packages/apidom-ast/src/nodes/yaml/YamlScalar.ts b/apidom/packages/apidom-ast/src/nodes/yaml/YamlScalar.ts new file mode 100644 index 0000000000..e53194549f --- /dev/null +++ b/apidom/packages/apidom-ast/src/nodes/yaml/YamlScalar.ts @@ -0,0 +1,21 @@ +import stampit from 'stampit'; + +import YamlNode from './YamlNode'; + +interface YamlScalar extends YamlNode { + value: string | null; +} + +const YamlScalar: stampit.Stamp = stampit(YamlNode, { + statics: { + type: 'scalar', + }, + props: { + value: null, + }, + init({ value = null } = {}) { + this.value = value; + }, +}); + +export default YamlScalar; diff --git a/apidom/packages/apidom-ast/src/nodes/yaml/YamlSeq.ts b/apidom/packages/apidom-ast/src/nodes/yaml/YamlSeq.ts new file mode 100644 index 0000000000..6f8ead5055 --- /dev/null +++ b/apidom/packages/apidom-ast/src/nodes/yaml/YamlSeq.ts @@ -0,0 +1,21 @@ +import stampit from 'stampit'; + +import YamlNode from './YamlNode'; + +interface YamlSeq extends YamlNode { + readonly items: Array; +} + +const YamlSeq: stampit.Stamp = stampit(YamlNode, { + statics: { + type: 'seq', + }, + methods: { + get items(): Array { + // @ts-ignore + return this.children; + }, + }, +}); + +export default YamlSeq; diff --git a/apidom/packages/apidom-ast/src/nodes/yaml/YamlSingleQuoteScalar.ts b/apidom/packages/apidom-ast/src/nodes/yaml/YamlSingleQuoteScalar.ts new file mode 100644 index 0000000000..bd475b9513 --- /dev/null +++ b/apidom/packages/apidom-ast/src/nodes/yaml/YamlSingleQuoteScalar.ts @@ -0,0 +1,13 @@ +import stampit from 'stampit'; + +import YamlScalar from './YamlScalar'; + +type YamlSingleQuoteScalar = YamlScalar; + +const YamlSingleQuoteScalar: stampit.Stamp = stampit(YamlScalar, { + statics: { + type: 'singleQuoteScalar', + }, +}); + +export default YamlSingleQuoteScalar; diff --git a/apidom/packages/apidom-ast/src/nodes/yaml/YamlStream.ts b/apidom/packages/apidom-ast/src/nodes/yaml/YamlStream.ts new file mode 100644 index 0000000000..2750a83724 --- /dev/null +++ b/apidom/packages/apidom-ast/src/nodes/yaml/YamlStream.ts @@ -0,0 +1,13 @@ +import stampit from 'stampit'; + +import YamlNode from './YamlNode'; + +type YamlStream = YamlNode; + +const YamlStream: stampit.Stamp = stampit(YamlNode, { + statics: { + type: 'stream', + }, +}); + +export default YamlStream; diff --git a/apidom/packages/apidom-ast/src/nodes/yaml/YamlTag.ts b/apidom/packages/apidom-ast/src/nodes/yaml/YamlTag.ts new file mode 100644 index 0000000000..5a9ff02a1b --- /dev/null +++ b/apidom/packages/apidom-ast/src/nodes/yaml/YamlTag.ts @@ -0,0 +1,21 @@ +import stampit from 'stampit'; + +import YamlNode from './YamlNode'; + +interface YamlTag extends YamlNode { + value: string | null; +} + +const YamlTag: stampit.Stamp = stampit(YamlNode, { + statics: { + type: 'tag', + }, + props: { + value: null, + }, + init({ value = null } = {}) { + this.value = value; + }, +}); + +export default YamlTag; diff --git a/apidom/packages/apidom-ast/src/nodes/yaml/predicates.ts b/apidom/packages/apidom-ast/src/nodes/yaml/predicates.ts new file mode 100644 index 0000000000..037f6a514f --- /dev/null +++ b/apidom/packages/apidom-ast/src/nodes/yaml/predicates.ts @@ -0,0 +1,29 @@ +import { anyPass } from 'ramda'; +import { isNodeType } from '../../predicates'; + +export const isStream = isNodeType('stream'); + +export const isDocument = isNodeType('document'); + +export const isMap = isNodeType('map'); + +export const isSeq = isNodeType('seq'); + +export const isPair = isNodeType('pair'); + +export const isTag = isNodeType('tag'); + +export const isPlainScalar = isNodeType('plainScalar'); + +export const isSingleQuoteScalar = isNodeType('singleQuoteScalar'); + +export const isDoubleQuoteScalar = isNodeType('doubleQuoteScalar'); + +export const isBlockScalar = isNodeType('blockScalar'); + +export const isScalar = anyPass([ + isPlainScalar, + isSingleQuoteScalar, + isDoubleQuoteScalar, + isBlockScalar, +]); diff --git a/apidom/packages/apidom-parser-adapter-asyncapi2-0-json/src/parser/visitors/generics/index.ts b/apidom/packages/apidom-parser-adapter-asyncapi2-0-json/src/parser/visitors/generics/index.ts index cce132960c..f441d3f4e8 100644 --- a/apidom/packages/apidom-parser-adapter-asyncapi2-0-json/src/parser/visitors/generics/index.ts +++ b/apidom/packages/apidom-parser-adapter-asyncapi2-0-json/src/parser/visitors/generics/index.ts @@ -216,7 +216,7 @@ export const ValueVisitor = stampit(SpecificationVisitor, { }, null(nullNode: JsonNull) { - const nullElement = new this.namespace.elements.Null(nullNode.value); + const nullElement = new this.namespace.elements.Null(); this.element = this.maybeAddSourceMap(nullNode, nullElement); return BREAK; }, diff --git a/apidom/packages/apidom-parser-adapter-openapi3-1-json/src/parser/visitors/generics/index.ts b/apidom/packages/apidom-parser-adapter-openapi3-1-json/src/parser/visitors/generics/index.ts index 0972145b97..4c3aa6f528 100644 --- a/apidom/packages/apidom-parser-adapter-openapi3-1-json/src/parser/visitors/generics/index.ts +++ b/apidom/packages/apidom-parser-adapter-openapi3-1-json/src/parser/visitors/generics/index.ts @@ -216,7 +216,7 @@ export const ValueVisitor = stampit(SpecificationVisitor, { }, null(nullNode: JsonNull) { - const nullElement = new this.namespace.elements.Null(nullNode.value); + const nullElement = new this.namespace.elements.Null(); this.element = this.maybeAddSourceMap(nullNode, nullElement); return BREAK; },