mirror of
https://github.com/danbulant/monaco-yaml
synced 2026-06-08 00:50:40 +00:00
Remove unused yaml parser module
This commit is contained in:
parent
39dcb0e50b
commit
6f8a8c5bbd
1 changed files with 0 additions and 326 deletions
|
|
@ -1,326 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import { JSONDocument, ASTNode, ErrorCode, BooleanASTNode, NullASTNode, ArrayASTNode, NumberASTNode, ObjectASTNode, PropertyASTNode, StringASTNode, IError, IApplicableSchema } from 'vscode-json-languageservice/lib/parser/jsonParser';
|
|
||||||
import { JSONSchema } from 'vscode-json-languageservice/lib/jsonSchema';
|
|
||||||
|
|
||||||
import * as nls from 'vscode-nls';
|
|
||||||
const localize = nls.loadMessageBundle();
|
|
||||||
|
|
||||||
import * as Yaml from '../../yaml-ast-parser/index'
|
|
||||||
import { Kind } from '../../yaml-ast-parser/index'
|
|
||||||
|
|
||||||
import { getLineStartPositions, getPosition } from '../documentPositionCalculator'
|
|
||||||
|
|
||||||
export class SingleYAMLDocument extends JSONDocument {
|
|
||||||
private lines;
|
|
||||||
public root;
|
|
||||||
|
|
||||||
constructor(lines: number[]) {
|
|
||||||
super({ disallowComments: false, ignoreDanglingComma: true });
|
|
||||||
this.lines = lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This is complicated, messy and probably buggy
|
|
||||||
// It should be re-written.
|
|
||||||
// To get the correct behavior, it probably needs to be aware of
|
|
||||||
// the type of the nodes it is processing since there are no delimiters
|
|
||||||
// like in JSON. (ie. so it correctly returns 'object' vs 'property')
|
|
||||||
public getNodeFromOffsetEndInclusive(offset: number): ASTNode {
|
|
||||||
if (!this.root) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (offset < this.root.start || offset > this.root.end) {
|
|
||||||
// We somehow are completely outside the document
|
|
||||||
// This is unexpected
|
|
||||||
console.log("Attempting to resolve node outside of document")
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const children = this.root.getChildNodes()
|
|
||||||
|
|
||||||
function* sliding2(nodes: ASTNode[]) {
|
|
||||||
var i = 0;
|
|
||||||
while (i < nodes.length) {
|
|
||||||
yield [nodes[i], (i === nodes.length) ? null : nodes[i + 1]]
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const onLaterLine = (offset: number, node: ASTNode) => {
|
|
||||||
const { line: actualLine } = getPosition(offset, this.lines)
|
|
||||||
const { line: nodeEndLine } = getPosition(node.end, this.lines)
|
|
||||||
|
|
||||||
return actualLine > nodeEndLine;
|
|
||||||
}
|
|
||||||
|
|
||||||
let findNode = (nodes: ASTNode[]): ASTNode => {
|
|
||||||
if (nodes.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var gen = sliding2(nodes);
|
|
||||||
|
|
||||||
let result: IteratorResult<ASTNode[]> = { done: false, value: undefined }
|
|
||||||
|
|
||||||
for (let [first, second] of gen) {
|
|
||||||
const end = (second) ? second.start : first.parent.end
|
|
||||||
if (offset >= first.start && offset < end) {
|
|
||||||
const children = first.getChildNodes();
|
|
||||||
|
|
||||||
const foundChild = findNode(children)
|
|
||||||
|
|
||||||
if (foundChild) {
|
|
||||||
if (foundChild['isKey'] && foundChild.end < offset) {
|
|
||||||
return foundChild.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundChild.type === "null") {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!foundChild && onLaterLine(offset, first)) {
|
|
||||||
return this.getNodeByIndent(this.lines, offset, this.root)
|
|
||||||
}
|
|
||||||
|
|
||||||
return foundChild || first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return findNode(children) || this.root;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getNodeFromOffset(offset: number): ASTNode {
|
|
||||||
return this.getNodeFromOffsetEndInclusive(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
private getNodeByIndent = (lines: number[], offset: number, node: ASTNode) => {
|
|
||||||
|
|
||||||
const { line, column: indent } = getPosition(offset, this.lines)
|
|
||||||
|
|
||||||
const children = node.getChildNodes()
|
|
||||||
|
|
||||||
function findNode(children) {
|
|
||||||
for (var idx = 0; idx < children.length; idx++) {
|
|
||||||
var child = children[idx];
|
|
||||||
|
|
||||||
const { line: childLine, column: childCol } = getPosition(child.start, lines);
|
|
||||||
|
|
||||||
if (childCol > indent) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newChildren = child.getChildNodes()
|
|
||||||
const foundNode = findNode(newChildren)
|
|
||||||
|
|
||||||
if (foundNode) {
|
|
||||||
return foundNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We have the right indentation, need to return based on line
|
|
||||||
if (childLine == line) {
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
if (childLine > line) {
|
|
||||||
// Get previous
|
|
||||||
(idx - 1) >= 0 ? children[idx - 1] : child;
|
|
||||||
}
|
|
||||||
// Else continue loop to try next element
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special case, we found the correct
|
|
||||||
return children[children.length - 1]
|
|
||||||
}
|
|
||||||
|
|
||||||
return findNode(children) || node
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function recursivelyBuildAst(parent: ASTNode, node: Yaml.YAMLNode): ASTNode {
|
|
||||||
|
|
||||||
if (!node) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (node.kind) {
|
|
||||||
case Yaml.Kind.MAP: {
|
|
||||||
const instance = <Yaml.YamlMap>node;
|
|
||||||
|
|
||||||
const result = new ObjectASTNode(parent, null, node.startPosition, node.endPosition)
|
|
||||||
result.addProperty
|
|
||||||
|
|
||||||
for (const mapping of instance.mappings) {
|
|
||||||
result.addProperty(<PropertyASTNode>recursivelyBuildAst(result, mapping))
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
case Yaml.Kind.MAPPING: {
|
|
||||||
const instance = <Yaml.YAMLMapping>node;
|
|
||||||
const key = instance.key;
|
|
||||||
|
|
||||||
// Technically, this is an arbitrary node in YAML
|
|
||||||
// I doubt we would get a better string representation by parsing it
|
|
||||||
const keyNode = new StringASTNode(null, null, true, key.startPosition, key.endPosition);
|
|
||||||
keyNode.value = key.value;
|
|
||||||
|
|
||||||
const result = new PropertyASTNode(parent, keyNode)
|
|
||||||
result.end = instance.endPosition
|
|
||||||
|
|
||||||
const valueNode = (instance.value) ? recursivelyBuildAst(result, instance.value) : new NullASTNode(parent, key.value, instance.endPosition, instance.endPosition)
|
|
||||||
valueNode.location = key.value
|
|
||||||
|
|
||||||
result.setValue(valueNode)
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
case Yaml.Kind.SEQ: {
|
|
||||||
const instance = <Yaml.YAMLSequence>node;
|
|
||||||
|
|
||||||
const result = new ArrayASTNode(parent, null, instance.startPosition, instance.endPosition);
|
|
||||||
|
|
||||||
let count = 0;
|
|
||||||
for (const item of instance.items) {
|
|
||||||
if (item === null && count === instance.items.length - 1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Be aware of https://github.com/nodeca/js-yaml/issues/321
|
|
||||||
// Cannot simply work around it here because we need to know if we are in Flow or Block
|
|
||||||
var itemNode = (item === null) ? new NullASTNode(parent, null, instance.endPosition, instance.endPosition) : recursivelyBuildAst(result, item);
|
|
||||||
|
|
||||||
itemNode.location = count++;
|
|
||||||
result.addItem(itemNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
case Yaml.Kind.SCALAR: {
|
|
||||||
const instance = <Yaml.YAMLScalar>node;
|
|
||||||
|
|
||||||
const type = Yaml.determineScalarType(instance)
|
|
||||||
|
|
||||||
// The name is set either by the sequence or the mapping case.
|
|
||||||
const name = null;
|
|
||||||
const value = instance.value;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case Yaml.ScalarType.null: {
|
|
||||||
return new NullASTNode(parent, name, instance.startPosition, instance.endPosition);
|
|
||||||
}
|
|
||||||
case Yaml.ScalarType.bool: {
|
|
||||||
return new BooleanASTNode(parent, name, Yaml.parseYamlBoolean(value), node.startPosition, node.endPosition)
|
|
||||||
}
|
|
||||||
case Yaml.ScalarType.int: {
|
|
||||||
const result = new NumberASTNode(parent, name, node.startPosition, node.endPosition);
|
|
||||||
result.value = Yaml.parseYamlInteger(value);
|
|
||||||
result.isInteger = true;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
case Yaml.ScalarType.float: {
|
|
||||||
const result = new NumberASTNode(parent, name, node.startPosition, node.endPosition);
|
|
||||||
result.value = Yaml.parseYamlFloat(value);
|
|
||||||
result.isInteger = false;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
case Yaml.ScalarType.string: {
|
|
||||||
const result = new StringASTNode(parent, name, false, node.startPosition, node.endPosition);
|
|
||||||
result.value = node.value;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Yaml.Kind.ANCHOR_REF: {
|
|
||||||
const instance = (<Yaml.YAMLAnchorReference>node).value
|
|
||||||
|
|
||||||
return recursivelyBuildAst(parent, instance) ||
|
|
||||||
new NullASTNode(parent, null, node.startPosition, node.endPosition);
|
|
||||||
}
|
|
||||||
case Yaml.Kind.INCLUDE_REF: {
|
|
||||||
// Issue Warning
|
|
||||||
console.log("Unsupported feature, node kind: " + node.kind);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertError(e: Yaml.YAMLException) {
|
|
||||||
// Subtract 2 because \n\0 is added by the parser (see loader.ts/loadDocuments)
|
|
||||||
const bufferLength = e.mark.buffer.length - 2;
|
|
||||||
|
|
||||||
// TODO determine correct positioning.
|
|
||||||
return { message: `${e.message}`, location: { start: Math.min(e.mark.position, bufferLength - 1), end: bufferLength, code: ErrorCode.Undefined } }
|
|
||||||
}
|
|
||||||
|
|
||||||
function createJSONDocument(yamlDoc: Yaml.YAMLNode, startPositions: number[]) {
|
|
||||||
let _doc = new SingleYAMLDocument(startPositions);
|
|
||||||
_doc.root = recursivelyBuildAst(null, yamlDoc)
|
|
||||||
|
|
||||||
if (!_doc.root) {
|
|
||||||
// TODO: When this is true, consider not pushing the other errors.
|
|
||||||
_doc.errors.push({ message: localize('Invalid symbol', 'Expected a YAML object, array or literal'), code: ErrorCode.Undefined, location: { start: yamlDoc.startPosition, end: yamlDoc.endPosition } });
|
|
||||||
}
|
|
||||||
|
|
||||||
const duplicateKeyReason = 'duplicate key'
|
|
||||||
|
|
||||||
const errors = yamlDoc.errors.filter(e => e.reason !== duplicateKeyReason && !e.isWarning).map(e => convertError(e))
|
|
||||||
const warnings = yamlDoc.errors.filter(e => e.reason === duplicateKeyReason || e.isWarning).map(e => convertError(e))
|
|
||||||
|
|
||||||
errors.forEach(e => _doc.errors.push(e));
|
|
||||||
warnings.forEach(e => _doc.warnings.push(e));
|
|
||||||
|
|
||||||
return _doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class YAMLDocument {
|
|
||||||
public documents: JSONDocument[]
|
|
||||||
|
|
||||||
constructor(documents: JSONDocument[]) {
|
|
||||||
this.documents = documents;
|
|
||||||
}
|
|
||||||
|
|
||||||
get errors(): IError[] {
|
|
||||||
return (<IError[]>[]).concat(...this.documents.map(d => d.errors))
|
|
||||||
}
|
|
||||||
|
|
||||||
get warnings(): IError[] {
|
|
||||||
return (<IError[]>[]).concat(...this.documents.map(d => d.warnings))
|
|
||||||
}
|
|
||||||
|
|
||||||
public getNodeFromOffsetEndInclusive(offset: number): ASTNode {
|
|
||||||
return this.getNodeFromOffset(offset);
|
|
||||||
}
|
|
||||||
public getNodeFromOffset(offset: number): ASTNode {
|
|
||||||
// Depends on the documents being sorted
|
|
||||||
for (let element of this.documents) {
|
|
||||||
if (offset <= element.root.end) {
|
|
||||||
return element.getNodeFromOffset(offset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
public validate(schema: JSONSchema, matchingSchemas: IApplicableSchema[] = null, offset: number = -1): void {
|
|
||||||
this.documents.forEach(doc => {
|
|
||||||
doc.validate(schema, matchingSchemas, offset)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parse(text: string): YAMLDocument {
|
|
||||||
|
|
||||||
const startPositions = getLineStartPositions(text)
|
|
||||||
// This is documented to return a YAMLNode even though the
|
|
||||||
// typing only returns a YAMLDocument
|
|
||||||
const yamlDocs = []
|
|
||||||
Yaml.loadAll(text, doc => yamlDocs.push(doc), {})
|
|
||||||
|
|
||||||
return new YAMLDocument(yamlDocs.map(doc => createJSONDocument(doc, startPositions)));
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue