Complete residential site build with Docker Compose & Gitea Actions deployment

This commit is contained in:
CalebLewallen
2026-05-13 17:31:20 -04:00
parent f9c4e13a50
commit 3c22823f72
19354 changed files with 2097331 additions and 0 deletions
@@ -0,0 +1,49 @@
import { Node, Pair } from 'yaml';
export type YamlNode = Node | Pair;
export type ASTNode = ObjectASTNode | PropertyASTNode | ArrayASTNode | StringASTNode | NumberASTNode | BooleanASTNode | NullASTNode;
export interface BaseASTNode {
readonly type: 'object' | 'array' | 'property' | 'string' | 'number' | 'boolean' | 'null';
readonly parent?: ASTNode;
readonly offset: number;
readonly length: number;
readonly children?: ASTNode[];
readonly value?: string | boolean | number | null;
readonly internalNode: YamlNode;
location: string;
getNodeFromOffsetEndInclusive(offset: number): ASTNode;
}
export interface ObjectASTNode extends BaseASTNode {
readonly type: 'object';
readonly properties: PropertyASTNode[];
readonly children: ASTNode[];
}
export interface PropertyASTNode extends BaseASTNode {
readonly type: 'property';
readonly keyNode: StringASTNode;
readonly valueNode?: ASTNode;
readonly colonOffset?: number;
readonly children: ASTNode[];
}
export interface ArrayASTNode extends BaseASTNode {
readonly type: 'array';
readonly items: ASTNode[];
readonly children: ASTNode[];
}
export interface StringASTNode extends BaseASTNode {
readonly type: 'string';
readonly value: string;
}
export interface NumberASTNode extends BaseASTNode {
readonly type: 'number';
readonly value: number;
readonly isInteger: boolean;
}
export interface BooleanASTNode extends BaseASTNode {
readonly type: 'boolean';
readonly value: boolean;
readonly source: string;
}
export interface NullASTNode extends BaseASTNode {
readonly type: 'null';
readonly value: null;
}
@@ -0,0 +1,6 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export {};
//# sourceMappingURL=jsonASTTypes.js.map
@@ -0,0 +1 @@
{"version":3,"file":"jsonASTTypes.js","sourceRoot":"","sources":["../../../src/languageservice/jsonASTTypes.ts"],"names":[],"mappings":"AAAA;;;gGAGgG"}
@@ -0,0 +1,103 @@
import { CompletionItemKind } from 'vscode-json-languageservice';
import { SchemaVersions } from './yamlTypes';
export type JSONSchemaRef = JSONSchema | boolean;
export declare enum SchemaDialect {
draft04 = "draft04",
draft07 = "draft07",
draft2019 = "draft2019-09",
draft2020 = "draft2020-12"
}
export interface JSONSchema {
_dialect?: SchemaDialect;
_baseUrl?: string;
_$ref?: string;
id?: string;
$id?: string;
$schema?: string;
url?: string;
type?: string | string[];
title?: string;
closestTitle?: string;
versions?: SchemaVersions;
default?: any;
definitions?: {
[name: string]: JSONSchema;
};
description?: string;
properties?: JSONSchemaMap;
patternProperties?: JSONSchemaMap;
additionalProperties?: JSONSchemaRef;
minProperties?: number;
maxProperties?: number;
dependencies?: JSONSchemaMap | {
[prop: string]: string[];
};
items?: JSONSchemaRef | JSONSchemaRef[];
minItems?: number;
maxItems?: number;
uniqueItems?: boolean;
additionalItems?: JSONSchemaRef;
pattern?: string;
minLength?: number;
maxLength?: number;
minimum?: number;
maximum?: number;
exclusiveMinimum?: boolean | number;
exclusiveMaximum?: boolean | number;
multipleOf?: number;
required?: string[];
$ref?: string;
anyOf?: JSONSchemaRef[];
allOf?: JSONSchemaRef[];
oneOf?: JSONSchemaRef[];
not?: JSONSchemaRef;
enum?: any[];
format?: string;
const?: any;
contains?: JSONSchemaRef;
propertyNames?: JSONSchemaRef;
examples?: any[];
$comment?: string;
if?: JSONSchemaRef;
then?: JSONSchemaRef;
else?: JSONSchemaRef;
$anchor?: string;
$defs?: {
[name: string]: JSONSchema;
};
$recursiveAnchor?: boolean;
$recursiveRef?: string;
$vocabulary?: Record<string, boolean>;
dependentSchemas?: JSONSchemaMap;
unevaluatedItems?: JSONSchemaRef;
unevaluatedProperties?: JSONSchemaRef;
dependentRequired?: Record<string, string[]>;
minContains?: number;
maxContains?: number;
prefixItems?: JSONSchemaRef[];
$dynamicRef?: string;
$dynamicAnchor?: string;
defaultSnippets?: {
label?: string;
description?: string;
markdownDescription?: string;
type?: string;
suggestionKind?: CompletionItemKind;
sortText?: string;
body?: any;
bodyText?: string;
}[];
errorMessage?: string;
patternErrorMessage?: string;
deprecationMessage?: string;
enumDescriptions?: string[];
markdownEnumDescriptions?: string[];
markdownDescription?: string;
doNotSuggest?: boolean;
allowComments?: boolean;
schemaSequence?: JSONSchema[];
filePatternAssociation?: string;
}
export interface JSONSchemaMap {
[name: string]: JSONSchemaRef;
}
@@ -0,0 +1,12 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export var SchemaDialect;
(function (SchemaDialect) {
SchemaDialect["draft04"] = "draft04";
SchemaDialect["draft07"] = "draft07";
SchemaDialect["draft2019"] = "draft2019-09";
SchemaDialect["draft2020"] = "draft2020-12";
})(SchemaDialect || (SchemaDialect = {}));
//# sourceMappingURL=jsonSchema.js.map
@@ -0,0 +1 @@
{"version":3,"file":"jsonSchema.js","sourceRoot":"","sources":["../../../src/languageservice/jsonSchema.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAMhG,MAAM,CAAN,IAAY,aAKX;AALD,WAAY,aAAa;IACvB,oCAAmB,CAAA;IACnB,oCAAmB,CAAA;IACnB,2CAA0B,CAAA;IAC1B,2CAA0B,CAAA;AAC5B,CAAC,EALW,aAAa,KAAb,aAAa,QAKxB"}
@@ -0,0 +1,11 @@
import { Alias, Document, LineCounter } from 'yaml';
import { ASTNode, YamlNode } from '../jsonASTTypes';
type NodeRange = [number, number, number];
export declare const aliasDepth: {
maxRefCount: number;
currentRefDepth: number;
aliasResolutionCache: Map<Alias, ASTNode>;
};
export declare function convertAST(parent: ASTNode, node: YamlNode, doc: Document, lineCounter: LineCounter): ASTNode | undefined;
export declare function toOffsetLength(range: NodeRange): [number, number];
export {};
@@ -0,0 +1,176 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { isScalar, isMap, isPair, isSeq, isNode, isAlias, } from 'yaml';
import { NullASTNodeImpl, PropertyASTNodeImpl, StringASTNodeImpl, ObjectASTNodeImpl, NumberASTNodeImpl, ArrayASTNodeImpl, BooleanASTNodeImpl, } from './jsonDocument';
// Exported for tests
export const aliasDepth = {
maxRefCount: 1000,
currentRefDepth: 0,
aliasResolutionCache: new Map(),
};
export function convertAST(parent, node, doc, lineCounter) {
if (!parent) {
// first invocation
aliasDepth.currentRefDepth = 0;
aliasDepth.aliasResolutionCache = new Map();
}
if (!node) {
return null;
}
if (isMap(node)) {
return convertMap(node, parent, doc, lineCounter);
}
if (isPair(node)) {
return convertPair(node, parent, doc, lineCounter);
}
if (isSeq(node)) {
return convertSeq(node, parent, doc, lineCounter);
}
if (isScalar(node)) {
return convertScalar(node, parent);
}
if (isAlias(node) && aliasDepth.currentRefDepth < aliasDepth.maxRefCount) {
return convertAlias(node, parent, doc, lineCounter);
}
else {
return;
}
}
function convertMap(node, parent, doc, lineCounter) {
let range;
if (node.flow && !node.range) {
range = collectFlowMapRange(node);
}
else {
range = node.range;
}
const result = new ObjectASTNodeImpl(parent, node, ...toFixedOffsetLength(range, lineCounter));
for (const it of node.items) {
if (isPair(it)) {
result.properties.push(convertAST(result, it, doc, lineCounter));
}
}
return result;
}
function convertPair(node, parent, doc, lineCounter) {
const keyNode = node.key;
const valueNode = node.value;
const rangeStart = keyNode.range[0];
let rangeEnd = keyNode.range[1];
let nodeEnd = keyNode.range[2];
if (valueNode) {
rangeEnd = valueNode.range[1];
nodeEnd = valueNode.range[2];
}
// Pair does not return a range using the key/value ranges to fake one.
const result = new PropertyASTNodeImpl(parent, node, ...toFixedOffsetLength([rangeStart, rangeEnd, nodeEnd], lineCounter));
if (isAlias(keyNode)) {
const keyAlias = new StringASTNodeImpl(parent, keyNode, ...toOffsetLength(keyNode.range));
keyAlias.value = keyNode.source;
result.keyNode = keyAlias;
}
else {
result.keyNode = convertAST(result, keyNode, doc, lineCounter);
}
result.valueNode = convertAST(result, valueNode, doc, lineCounter);
return result;
}
function convertSeq(node, parent, doc, lineCounter) {
const result = new ArrayASTNodeImpl(parent, node, ...toOffsetLength(node.range));
for (const it of node.items) {
if (isNode(it)) {
const convertedNode = convertAST(result, it, doc, lineCounter);
// due to recursion protection, convertAST may return undefined
if (convertedNode) {
result.children.push(convertedNode);
}
}
}
return result;
}
function convertScalar(node, parent) {
if (node.value === null) {
return new NullASTNodeImpl(parent, node, ...toOffsetLength(node.range));
}
switch (typeof node.value) {
case 'string': {
const result = new StringASTNodeImpl(parent, node, ...toOffsetLength(node.range));
result.value = node.value;
return result;
}
case 'boolean':
return new BooleanASTNodeImpl(parent, node, node.value, node.source, ...toOffsetLength(node.range));
case 'number': {
const result = new NumberASTNodeImpl(parent, node, ...toOffsetLength(node.range));
result.value = node.value;
result.isInteger = Number.isInteger(result.value);
return result;
}
default: {
// fail safe converting, we need to return some node anyway
const result = new StringASTNodeImpl(parent, node, ...toOffsetLength(node.range));
result.value = node.source;
return result;
}
}
}
function convertAlias(node, parent, doc, lineCounter) {
if (aliasDepth.aliasResolutionCache.has(node)) {
return aliasDepth.aliasResolutionCache.get(node);
}
aliasDepth.currentRefDepth++;
const resolvedNode = node.resolve(doc);
let ans;
if (resolvedNode) {
ans = convertAST(parent, resolvedNode, doc, lineCounter);
}
else {
const resultNode = new StringASTNodeImpl(parent, node, ...toOffsetLength(node.range));
resultNode.value = node.source;
ans = resultNode;
}
aliasDepth.currentRefDepth--;
aliasDepth.aliasResolutionCache.set(node, ans);
return ans;
}
export function toOffsetLength(range) {
return [range[0], range[1] - range[0]];
}
/**
* Convert offsets to offset+length with fix length to not include '\n' character in some cases
* @param range the yaml ast range
* @param lineCounter the line counter
* @returns the offset and length
*/
function toFixedOffsetLength(range, lineCounter) {
const start = lineCounter.linePos(range[0]);
const end = lineCounter.linePos(range[1]);
const result = [range[0], range[1] - range[0]];
// -1 as range may include '\n'
if (start.line !== end.line && (lineCounter.lineStarts.length !== end.line || end.col === 1)) {
result[1]--;
}
return result;
}
function collectFlowMapRange(node) {
let start = Number.MAX_SAFE_INTEGER;
let end = 0;
for (const it of node.items) {
if (isPair(it)) {
if (isNode(it.key)) {
if (it.key.range && it.key.range[0] <= start) {
start = it.key.range[0];
}
}
if (isNode(it.value)) {
if (it.value.range && it.value.range[2] >= end) {
end = it.value.range[2];
}
}
}
}
return [start, end, end];
}
//# sourceMappingURL=ast-converter.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,4 @@
import type { ASTNode } from '../jsonASTTypes';
export declare function getNodeValue(node: ASTNode): any;
export declare function contains(node: ASTNode, offset: number, includeRightBound?: boolean): boolean;
export declare function findNodeAtOffset(node: ASTNode, offset: number, includeRightBound: boolean): ASTNode;
@@ -0,0 +1,48 @@
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function getNodeValue(node) {
switch (node.type) {
case 'array':
return node.children.map(getNodeValue);
case 'object': {
const obj = Object.create(null);
for (let _i = 0, _a = node.children; _i < _a.length; _i++) {
const prop = _a[_i];
const valueNode = prop.children[1];
if (valueNode) {
obj[prop.children[0].value] = getNodeValue(valueNode);
}
}
return obj;
}
case 'null':
case 'string':
case 'number':
return node.value;
case 'boolean':
return node.source;
default:
return undefined;
}
}
export function contains(node, offset, includeRightBound = false) {
return ((offset >= node.offset && offset <= node.offset + node.length) || (includeRightBound && offset === node.offset + node.length));
}
export function findNodeAtOffset(node, offset, includeRightBound) {
if (includeRightBound === void 0) {
includeRightBound = false;
}
if (contains(node, offset, includeRightBound)) {
const children = node.children;
if (Array.isArray(children)) {
for (let i = 0; i < children.length && children[i].offset <= offset; i++) {
const item = findNodeAtOffset(children[i], offset, includeRightBound);
if (item) {
return item;
}
}
}
return node;
}
return undefined;
}
//# sourceMappingURL=astNodeUtils.js.map
@@ -0,0 +1 @@
{"version":3,"file":"astNodeUtils.js","sourceRoot":"","sources":["../../../../src/languageservice/parser/astNodeUtils.ts"],"names":[],"mappings":"AAEA,8DAA8D;AAC9D,MAAM,UAAU,YAAY,CAAC,IAAa;IACxC,QAAQ,IAAI,CAAC,IAAI,EAAE;QACjB,KAAK,OAAO;YACV,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACzC,KAAK,QAAQ,CAAC,CAAC;YACb,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAChC,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE;gBACzD,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;gBACpB,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBACnC,IAAI,SAAS,EAAE;oBACb,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAe,CAAC,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;iBACjE;aACF;YACD,OAAO,GAAG,CAAC;SACZ;QACD,KAAK,MAAM,CAAC;QACZ,KAAK,QAAQ,CAAC;QACd,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC,KAAK,CAAC;QACpB,KAAK,SAAS;YACZ,OAAO,IAAI,CAAC,MAAM,CAAC;QACrB;YACE,OAAO,SAAS,CAAC;KACpB;AACH,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAa,EAAE,MAAc,EAAE,iBAAiB,GAAG,KAAK;IAC/E,OAAO,CACL,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,IAAI,MAAM,KAAK,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAC9H,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAa,EAAE,MAAc,EAAE,iBAA0B;IACxF,IAAI,iBAAiB,KAAK,KAAK,CAAC,EAAE;QAChC,iBAAiB,GAAG,KAAK,CAAC;KAC3B;IACD,IAAI,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;YAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC,EAAE,EAAE;gBACxE,MAAM,IAAI,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC;gBACtE,IAAI,IAAI,EAAE;oBACR,OAAO,IAAI,CAAC;iBACb;aACF;SACF;QACD,OAAO,IAAI,CAAC;KACb;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,7 @@
import { Tags } from 'yaml';
/**
* Converts the tags from settings and adds known tags such as !include
* and returns Tags that can be used by the parser.
* @param customTags Tags for parser
*/
export declare function getCustomTags(customTags: string[]): Tags;
@@ -0,0 +1,58 @@
import { isSeq, isMap } from 'yaml';
import { filterInvalidCustomTags } from '../utils/arrUtils';
class CommonTagImpl {
constructor(tag, type) {
this.tag = tag;
this.type = type;
}
get collection() {
if (this.type === 'mapping') {
return 'map';
}
if (this.type === 'sequence') {
return 'seq';
}
return undefined;
}
resolve(value) {
if (isMap(value) && this.type === 'mapping') {
return value;
}
if (isSeq(value) && this.type === 'sequence') {
return value;
}
if (typeof value === 'string' && this.type === 'scalar') {
return value;
}
}
}
class IncludeTag {
constructor() {
this.tag = '!include';
this.type = 'scalar';
}
resolve(value, onError) {
if (value && value.length > 0 && value.trim()) {
return value;
}
onError('!include without value');
}
}
/**
* Converts the tags from settings and adds known tags such as !include
* and returns Tags that can be used by the parser.
* @param customTags Tags for parser
*/
export function getCustomTags(customTags) {
const tags = [];
const filteredTags = filterInvalidCustomTags(customTags);
for (const tag of filteredTags) {
const typeInfo = tag.split(' ');
const tagName = typeInfo[0];
const tagType = (typeInfo[1] && typeInfo[1].toLowerCase()) || 'scalar';
tags.push(new CommonTagImpl(tagName, tagType));
}
tags.push(new IncludeTag());
return tags;
}
//# sourceMappingURL=custom-tag-provider.js.map
@@ -0,0 +1 @@
{"version":3,"file":"custom-tag-provider.js","sourceRoot":"","sources":["../../../../src/languageservice/parser/custom-tag-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,EAAE,KAAK,EAAoB,MAAM,MAAM,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,MAAM,aAAa;IAIjB,YAAY,GAAW,EAAE,IAAY;QACnC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IACD,IAAI,UAAU;QACZ,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE;YAC3B,OAAO,KAAK,CAAC;SACd;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE;YAC5B,OAAO,KAAK,CAAC;SACd;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,CAAC,KAAiC;QACvC,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE;YAC3C,OAAO,KAAK,CAAC;SACd;QACD,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE;YAC5C,OAAO,KAAK,CAAC;SACd;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE;YACvD,OAAO,KAAK,CAAC;SACd;IACH,CAAC;CACF;AAED,MAAM,UAAU;IAAhB;QACkB,QAAG,GAAG,UAAU,CAAC;QACjB,SAAI,GAAG,QAAQ,CAAC;IAUlC,CAAC;IANC,OAAO,CAAC,KAAa,EAAE,OAAkC;QACvD,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE;YAC7C,OAAO,KAAK,CAAC;SACd;QACD,OAAO,CAAC,wBAAwB,CAAC,CAAC;IACpC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,UAAoB;IAChD,MAAM,IAAI,GAAG,EAAE,CAAC;IAChB,MAAM,YAAY,GAAG,uBAAuB,CAAC,UAAU,CAAC,CAAC;IACzD,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE;QAC9B,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,QAAQ,CAAC;QACvE,IAAI,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;KAChD;IACD,IAAI,CAAC,IAAI,CAAC,IAAI,UAAU,EAAE,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,4 @@
import { TextDocument } from 'vscode-languageserver-textdocument';
import * as Parser from './jsonDocument';
export declare function setKubernetesParserOption(jsonDocuments: Parser.JSONDocument[], option: boolean): void;
export declare function isKubernetesAssociatedDocument(textDocument: TextDocument, paths: string[]): boolean;
@@ -0,0 +1,17 @@
import { FilePatternAssociation } from '../utils/filePatternAssociation';
export function setKubernetesParserOption(jsonDocuments, option) {
for (const jsonDoc of jsonDocuments) {
jsonDoc.isKubernetes = option;
}
}
export function isKubernetesAssociatedDocument(textDocument, paths) {
for (const path in paths) {
const globPath = paths[path];
const fpa = new FilePatternAssociation(globPath);
if (fpa.matchesPattern(textDocument.uri)) {
return true;
}
}
return false;
}
//# sourceMappingURL=isKubernetes.js.map
@@ -0,0 +1 @@
{"version":3,"file":"isKubernetes.js","sourceRoot":"","sources":["../../../../src/languageservice/parser/isKubernetes.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGzE,MAAM,UAAU,yBAAyB,CAAC,aAAoC,EAAE,MAAe;IAC7F,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE;QACnC,OAAO,CAAC,YAAY,GAAG,MAAM,CAAC;KAC/B;AACH,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,YAA0B,EAAE,KAAe;IACxF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;QACxB,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,GAAG,GAAG,IAAI,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QAEjD,IAAI,GAAG,CAAC,cAAc,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE;YACxC,OAAO,IAAI,CAAC;SACb;KACF;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,83 @@
import { JSONSchema } from '../jsonSchema';
import { ASTNode, ObjectASTNode, ArrayASTNode, BooleanASTNode, NumberASTNode, StringASTNode, NullASTNode, PropertyASTNode, YamlNode } from '../jsonASTTypes';
import { Diagnostic, Range } from 'vscode-languageserver-types';
import { TextDocument } from 'vscode-languageserver-textdocument';
import { Node, Pair } from 'yaml';
import { type IApplicableSchema } from './schemaValidation/baseValidator';
declare abstract class ASTNodeImpl {
abstract readonly type: 'object' | 'property' | 'array' | 'number' | 'boolean' | 'null' | 'string';
offset: number;
length: number;
readonly parent: ASTNode;
location: string;
readonly internalNode: YamlNode;
constructor(parent: ASTNode, internalNode: YamlNode, offset: number, length?: number);
getNodeFromOffsetEndInclusive(offset: number): ASTNode;
get children(): ASTNode[];
toString(): string;
}
export declare class NullASTNodeImpl extends ASTNodeImpl implements NullASTNode {
type: 'null';
value: any;
constructor(parent: ASTNode, internalNode: Node, offset: number, length?: number);
}
export declare class BooleanASTNodeImpl extends ASTNodeImpl implements BooleanASTNode {
type: 'boolean';
value: boolean;
source: string;
constructor(parent: ASTNode, internalNode: Node, boolValue: boolean, boolSource: string, offset: number, length?: number);
}
export declare class ArrayASTNodeImpl extends ASTNodeImpl implements ArrayASTNode {
type: 'array';
items: ASTNode[];
constructor(parent: ASTNode, internalNode: Node, offset: number, length?: number);
get children(): ASTNode[];
}
export declare class NumberASTNodeImpl extends ASTNodeImpl implements NumberASTNode {
type: 'number';
isInteger: boolean;
value: number;
constructor(parent: ASTNode, internalNode: Node, offset: number, length?: number);
}
export declare class StringASTNodeImpl extends ASTNodeImpl implements StringASTNode {
type: 'string';
value: string;
constructor(parent: ASTNode, internalNode: Node, offset: number, length?: number);
}
export declare class PropertyASTNodeImpl extends ASTNodeImpl implements PropertyASTNode {
type: 'property';
keyNode: StringASTNode;
valueNode: ASTNode;
colonOffset: number;
constructor(parent: ObjectASTNode, internalNode: Pair, offset: number, length?: number);
get children(): ASTNode[];
}
export declare class ObjectASTNodeImpl extends ASTNodeImpl implements ObjectASTNode {
type: 'object';
properties: PropertyASTNode[];
constructor(parent: ASTNode, internalNode: Node, offset: number, length?: number);
get children(): ASTNode[];
}
export interface JSONDocumentConfig {
collectComments?: boolean;
}
export declare enum EnumMatch {
Key = 0,
Enum = 1
}
export declare function newJSONDocument(root: ASTNode, diagnostics?: Diagnostic[]): JSONDocument;
export declare class JSONDocument {
readonly root: ASTNode;
readonly syntaxErrors: Diagnostic[];
readonly comments: Range[];
isKubernetes: boolean;
disableAdditionalProperties: boolean;
uri: string;
constructor(root: ASTNode, syntaxErrors?: Diagnostic[], comments?: Range[]);
getNodeFromOffset(offset: number, includeRightBound?: boolean): ASTNode | undefined;
getNodeFromOffsetEndInclusive(offset: number): ASTNode;
visit(visitor: (node: ASTNode) => boolean): void;
validate(textDocument: TextDocument, schema: JSONSchema): Diagnostic[];
getMatchingSchemas(schema: JSONSchema, focusOffset?: number, exclude?: ASTNode, didCallFromAutoComplete?: boolean): IApplicableSchema[];
}
export {};
@@ -0,0 +1,171 @@
import { findNodeAtOffset } from './astNodeUtils';
import { getValidator } from './schemaValidation/validatorFactory';
class ASTNodeImpl {
constructor(parent, internalNode, offset, length) {
this.offset = offset;
this.length = length;
this.parent = parent;
this.internalNode = internalNode;
}
getNodeFromOffsetEndInclusive(offset) {
const collector = [];
const findNode = (node) => {
if (offset >= node.offset && offset <= node.offset + node.length) {
const children = node.children;
for (let i = 0; i < children.length && children[i].offset <= offset; i++) {
const item = findNode(children[i]);
if (item) {
collector.push(item);
}
}
return node;
}
return null;
};
const foundNode = findNode(this);
let currMinDist = Number.MAX_VALUE;
let currMinNode = null;
for (const currNode of collector) {
const minDist = currNode.length + currNode.offset - offset + (offset - currNode.offset);
if (minDist < currMinDist) {
currMinNode = currNode;
currMinDist = minDist;
}
}
return currMinNode || foundNode;
}
get children() {
return [];
}
toString() {
return ('type: ' +
this.type +
' (' +
this.offset +
'/' +
this.length +
')' +
(this.parent ? ' parent: {' + this.parent.toString() + '}' : ''));
}
}
export class NullASTNodeImpl extends ASTNodeImpl {
constructor(parent, internalNode, offset, length) {
super(parent, internalNode, offset, length);
this.type = 'null';
this.value = null;
}
}
export class BooleanASTNodeImpl extends ASTNodeImpl {
constructor(parent, internalNode, boolValue, boolSource, offset, length) {
super(parent, internalNode, offset, length);
this.type = 'boolean';
this.value = boolValue;
this.source = boolSource;
}
}
export class ArrayASTNodeImpl extends ASTNodeImpl {
constructor(parent, internalNode, offset, length) {
super(parent, internalNode, offset, length);
this.type = 'array';
this.items = [];
}
get children() {
return this.items;
}
}
export class NumberASTNodeImpl extends ASTNodeImpl {
constructor(parent, internalNode, offset, length) {
super(parent, internalNode, offset, length);
this.type = 'number';
this.isInteger = true;
this.value = Number.NaN;
}
}
export class StringASTNodeImpl extends ASTNodeImpl {
constructor(parent, internalNode, offset, length) {
super(parent, internalNode, offset, length);
this.type = 'string';
this.value = '';
}
}
export class PropertyASTNodeImpl extends ASTNodeImpl {
constructor(parent, internalNode, offset, length) {
super(parent, internalNode, offset, length);
this.type = 'property';
this.colonOffset = -1;
}
get children() {
return this.valueNode ? [this.keyNode, this.valueNode] : [this.keyNode];
}
}
export class ObjectASTNodeImpl extends ASTNodeImpl {
constructor(parent, internalNode, offset, length) {
super(parent, internalNode, offset, length);
this.type = 'object';
this.properties = [];
}
get children() {
return this.properties;
}
}
export var EnumMatch;
(function (EnumMatch) {
EnumMatch[EnumMatch["Key"] = 0] = "Key";
EnumMatch[EnumMatch["Enum"] = 1] = "Enum";
})(EnumMatch || (EnumMatch = {}));
export function newJSONDocument(root, diagnostics = []) {
return new JSONDocument(root, diagnostics, []);
}
export class JSONDocument {
constructor(root, syntaxErrors = [], comments = []) {
this.root = root;
this.syntaxErrors = syntaxErrors;
this.comments = comments;
}
getNodeFromOffset(offset, includeRightBound = false) {
if (this.root) {
return findNodeAtOffset(this.root, offset, includeRightBound);
}
return undefined;
}
getNodeFromOffsetEndInclusive(offset) {
return this.root && this.root.getNodeFromOffsetEndInclusive(offset);
}
visit(visitor) {
if (this.root) {
const doVisit = (node) => {
let ctn = visitor(node);
const children = node.children;
if (Array.isArray(children)) {
for (let i = 0; i < children.length && ctn; i++) {
ctn = doVisit(children[i]);
}
}
return ctn;
};
doVisit(this.root);
}
}
validate(textDocument, schema) {
if (!this.root || !schema)
return null;
const validator = getValidator(schema._dialect);
return validator.validateDocument(this.root, textDocument, schema, {
isKubernetes: this.isKubernetes,
disableAdditionalProperties: this.disableAdditionalProperties,
uri: this.uri,
});
}
getMatchingSchemas(schema, focusOffset = -1, exclude = null, didCallFromAutoComplete) {
if (!this.root || !schema)
return [];
const validator = getValidator(schema._dialect);
return validator.getMatchingSchemas(this.root, schema, {
isKubernetes: this.isKubernetes,
disableAdditionalProperties: this.disableAdditionalProperties,
uri: this.uri,
callFromAutoComplete: didCallFromAutoComplete,
}, focusOffset, exclude);
}
}
//# sourceMappingURL=jsonDocument.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
/**
* Parse a boolean according to the specification
*
* Return:
* true if its a true value
* false if its a false value
*/
export declare function parseYamlBoolean(input: string): boolean;
@@ -0,0 +1,17 @@
/**
* Parse a boolean according to the specification
*
* Return:
* true if its a true value
* false if its a false value
*/
export function parseYamlBoolean(input) {
if (['true', 'True', 'TRUE', 'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON'].lastIndexOf(input) >= 0) {
return true;
}
else if (['false', 'False', 'FALSE', 'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'].lastIndexOf(input) >= 0) {
return false;
}
throw `Invalid boolean "${input}"`;
}
//# sourceMappingURL=scalar-type.js.map
@@ -0,0 +1 @@
{"version":3,"file":"scalar-type.js","sourceRoot":"","sources":["../../../../src/languageservice/parser/scalar-type.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;QACrG,OAAO,IAAI,CAAC;KACb;SAAM,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;QAC/G,OAAO,KAAK,CAAC;KACd;IACD,MAAM,oBAAoB,KAAK,GAAG,CAAC;AACrC,CAAC"}
@@ -0,0 +1,124 @@
import type { JSONSchema, JSONSchemaRef, SchemaDialect } from '../../jsonSchema';
import type { ASTNode, ArrayASTNode, NumberASTNode, ObjectASTNode, StringASTNode } from '../../jsonASTTypes';
import { ErrorCode } from 'vscode-json-languageservice';
import { Diagnostic, DiagnosticSeverity } from 'vscode-languageserver-types';
import type { TextDocument } from 'vscode-languageserver-textdocument';
export declare const YAML_SOURCE = "YAML";
export interface IRange {
offset: number;
length: number;
}
export declare enum ProblemType {
missingRequiredPropWarning = "missingRequiredPropWarning",
typeMismatchWarning = "typeMismatchWarning",
constWarning = "constWarning"
}
export declare const ProblemTypeMessages: Record<ProblemType, string>;
export interface IProblem {
location: IRange;
severity: DiagnosticSeverity;
code?: ErrorCode;
message: string;
source?: string;
problemType?: ProblemType;
problemArgs?: string[];
schemaUri?: string[];
data?: Record<string, unknown>;
}
export interface IApplicableSchema {
node: ASTNode;
inverted?: boolean;
schema: JSONSchema;
}
export interface ISchemaCollector {
schemas: IApplicableSchema[];
add(schema: IApplicableSchema): void;
merge(other: ISchemaCollector): void;
include(node: ASTNode): boolean;
newSub(): ISchemaCollector;
}
export declare const formats: Record<string, {
errorMessage: string;
pattern: RegExp;
}>;
export declare class ValidationResult {
problems: IProblem[];
propertiesMatches: number;
propertiesValueMatches: number;
primaryValueMatches: number;
enumValueMatch: boolean;
enumValues: any[];
/**
* Optional bookkeeping for newer drafts (2019/2020).
* BaseValidator only populates evaluatedProperties conservatively for object keywords it processes directly.
*/
evaluatedProperties?: Set<string>;
evaluatedItemsByNode?: Map<ASTNode, Set<number>>;
constructor(isKubernetes: boolean);
getEvaluatedItems(node: ASTNode): Set<number>;
hasProblems(): boolean;
merge(other: ValidationResult): void;
mergeEnumValues(other: ValidationResult): void;
mergeWarningGeneric(sub: ValidationResult, problemTypesToMerge: ProblemType[]): void;
mergePropertyMatch(propertyValidationResult: ValidationResult, mergeEvaluated?: boolean): void;
private mergeSources;
compareGeneric(other: ValidationResult): number;
compareKubernetes(other: ValidationResult): number;
}
export interface Options {
isKubernetes: boolean;
disableAdditionalProperties: boolean;
uri: string;
callFromAutoComplete?: boolean;
}
interface IValidationMatch {
schema: JSONSchema;
validationResult: ValidationResult;
matchingSchemas: ISchemaCollector;
}
export declare abstract class BaseValidator {
protected collectSeenKeys(node: ObjectASTNode): Record<string, ASTNode>;
validateDocument(root: ASTNode, textDocument: TextDocument, schema: JSONSchema, options: Options): Diagnostic[];
getMatchingSchemas(root: ASTNode, schema: JSONSchema, options: Options, focusOffset: number, exclude: ASTNode | null): IApplicableSchema[];
protected getNoOpCollector(): ISchemaCollector;
protected getSchemaSource(schema: JSONSchema, originalSchema: JSONSchema): string;
protected getSchemaUri(schema: JSONSchema, originalSchema: JSONSchema): string[];
/**
* Draft-specific hook: interpret numeric bounds in the drafts way.
* - Draft07+: numeric exclusiveMinimum/exclusiveMaximum
* - Draft04: boolean exclusiveMinimum/exclusiveMaximum that modify minimum/maximum
*/
protected abstract getNumberLimits(schema: JSONSchema): {
minimum?: number;
maximum?: number;
exclusiveMinimum?: number;
exclusiveMaximum?: number;
};
/**
* Get the current validator's dialect.
*/
protected abstract getCurrentDialect(): SchemaDialect;
protected validateNode(node: ASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, matchingSchemas: ISchemaCollector, options: Options): void;
protected validateGenericNode(node: ASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, matchingSchemas: ISchemaCollector, options: Options): void;
protected validateStringNode(node: StringASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult): void;
protected validateNumberNode(node: NumberASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult): void;
protected validateArrayNode(node: ArrayASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, matchingSchemas: ISchemaCollector, options: Options): void;
protected applyContains(node: ArrayASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, _matchingSchemas: ISchemaCollector, options: Options): void;
protected applyArrayLength(node: ArrayASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, _options: Options): void;
protected applyUniqueItems(node: ArrayASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult): void;
protected validateObjectNode(node: ObjectASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, matchingSchemas: ISchemaCollector, options: Options): void;
protected applyRequired(node: ObjectASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, _options: Options, seenKeys: Record<string, ASTNode>): void;
protected applyProperties(_node: ObjectASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, matchingSchemas: ISchemaCollector, options: Options, seenKeys: Record<string, ASTNode>, _unprocessedProperties: string[], propertyProcessed: (prop: string) => void): void;
protected applyPatternProperties(_node: ObjectASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, matchingSchemas: ISchemaCollector, options: Options, seenKeys: Record<string, ASTNode>, unprocessedProperties: string[], propertyProcessed: (prop: string) => void): void;
protected applyAdditionalProperties(_node: ObjectASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, matchingSchemas: ISchemaCollector, options: Options, seenKeys: Record<string, ASTNode>, unprocessedProperties: string[]): void;
protected applyPropertyCount(node: ObjectASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult): void;
protected applyDependencies(node: ObjectASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, matchingSchemas: ISchemaCollector, options: Options, seenKeys: Record<string, ASTNode>): void;
protected applyPropertyNames(node: ObjectASTNode, schema: JSONSchema, validationResult: ValidationResult, options: Options): void;
protected applyUnevaluatedProperties(_node: ObjectASTNode, _schema: JSONSchema, _originalSchema: JSONSchema, _validationResult: ValidationResult, _matchingSchemas: ISchemaCollector, _options: Options, _seenKeys?: Record<string, ASTNode>, _unprocessedProperties?: string[]): void;
protected applyUnevaluatedItems(_node: ArrayASTNode | ASTNode, _schema: JSONSchema, _originalSchema: JSONSchema, _validationResult: ValidationResult, _matchingSchemas: ISchemaCollector, _options: Options): void;
protected alternativeComparison(subValidationResult: ValidationResult, bestMatch: IValidationMatch, subSchema: JSONSchema, subMatchingSchemas: ISchemaCollector): IValidationMatch;
protected genericComparison(node: ASTNode, maxOneMatch: boolean, subValidationResult: ValidationResult, bestMatch: IValidationMatch, subSchema: JSONSchema, subMatchingSchemas: ISchemaCollector): IValidationMatch;
protected mergeValidationMatches(bestMatch: IValidationMatch, subMatchingSchemas: ISchemaCollector, subValidationResult: ValidationResult): void;
}
export declare function asSchema(schema: JSONSchemaRef): JSONSchema | undefined;
export {};
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,17 @@
import type { JSONSchema } from '../../jsonSchema';
import { SchemaDialect } from '../../jsonSchema';
import { BaseValidator } from './baseValidator';
export declare class Draft04Validator extends BaseValidator {
protected getCurrentDialect(): SchemaDialect;
/**
* Keyword: exclusiveMinimum/exclusiveMaximum
*
* Booleans that make minimum/maximum exclusive.
*/
protected getNumberLimits(schema: JSONSchema): {
minimum?: number;
maximum?: number;
exclusiveMinimum?: number;
exclusiveMaximum?: number;
};
}
@@ -0,0 +1,30 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) IBM Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { SchemaDialect } from '../../jsonSchema';
import { isBoolean, isNumber } from '../../utils/objects';
import { BaseValidator } from './baseValidator';
export class Draft04Validator extends BaseValidator {
getCurrentDialect() {
return SchemaDialect.draft04;
}
/**
* Keyword: exclusiveMinimum/exclusiveMaximum
*
* Booleans that make minimum/maximum exclusive.
*/
getNumberLimits(schema) {
const minimum = isNumber(schema.minimum) ? schema.minimum : undefined;
const maximum = isNumber(schema.maximum) ? schema.maximum : undefined;
const exclusiveMinimum = isBoolean(schema.exclusiveMinimum) && schema.exclusiveMinimum ? minimum : undefined;
const exclusiveMaximum = isBoolean(schema.exclusiveMaximum) && schema.exclusiveMaximum ? maximum : undefined;
return {
minimum: exclusiveMinimum === undefined ? minimum : undefined,
maximum: exclusiveMaximum === undefined ? maximum : undefined,
exclusiveMinimum,
exclusiveMaximum,
};
}
}
//# sourceMappingURL=draft04Validator.js.map
@@ -0,0 +1 @@
{"version":3,"file":"draft04Validator.js","sourceRoot":"","sources":["../../../../../src/languageservice/parser/schemaValidation/draft04Validator.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAGhG,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,OAAO,gBAAiB,SAAQ,aAAa;IAC9B,iBAAiB;QAClC,OAAO,aAAa,CAAC,OAAO,CAAC;IAC/B,CAAC;IAED;;;;OAIG;IACgB,eAAe,CAAC,MAAkB;QAMnD,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QACtE,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QAEtE,MAAM,gBAAgB,GAAG,SAAS,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7G,MAAM,gBAAgB,GAAG,SAAS,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QAE7G,OAAO;YACL,OAAO,EAAE,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;YAC7D,OAAO,EAAE,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;YAC7D,gBAAgB;YAChB,gBAAgB;SACjB,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,15 @@
import type { JSONSchema } from '../../jsonSchema';
import { SchemaDialect } from '../../jsonSchema';
import { BaseValidator } from './baseValidator';
export declare class Draft07Validator extends BaseValidator {
protected getCurrentDialect(): SchemaDialect;
/**
* Keyword: exclusiveMinimum/exclusiveMaximum are treated as numeric bounds
*/
protected getNumberLimits(schema: JSONSchema): {
minimum?: number;
maximum?: number;
exclusiveMinimum?: number;
exclusiveMaximum?: number;
};
}
@@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) IBM Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { SchemaDialect } from '../../jsonSchema';
import { isNumber } from '../../utils/objects';
import { BaseValidator } from './baseValidator';
export class Draft07Validator extends BaseValidator {
getCurrentDialect() {
return SchemaDialect.draft07;
}
/**
* Keyword: exclusiveMinimum/exclusiveMaximum are treated as numeric bounds
*/
getNumberLimits(schema) {
const minimum = isNumber(schema.minimum) ? schema.minimum : undefined;
const maximum = isNumber(schema.maximum) ? schema.maximum : undefined;
const exclusiveMinimum = isNumber(schema.exclusiveMinimum) ? schema.exclusiveMinimum : undefined;
const exclusiveMaximum = isNumber(schema.exclusiveMaximum) ? schema.exclusiveMaximum : undefined;
return {
minimum: exclusiveMinimum === undefined ? minimum : undefined,
maximum: exclusiveMaximum === undefined ? maximum : undefined,
exclusiveMinimum,
exclusiveMaximum,
};
}
}
//# sourceMappingURL=draft07Validator.js.map
@@ -0,0 +1 @@
{"version":3,"file":"draft07Validator.js","sourceRoot":"","sources":["../../../../../src/languageservice/parser/schemaValidation/draft07Validator.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAGhG,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,OAAO,gBAAiB,SAAQ,aAAa;IAC9B,iBAAiB;QAClC,OAAO,aAAa,CAAC,OAAO,CAAC;IAC/B,CAAC;IAED;;OAEG;IACO,eAAe,CAAC,MAAkB;QAM1C,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QACtE,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QAEtE,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;QACjG,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;QAEjG,OAAO;YACL,OAAO,EAAE,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;YAC7D,OAAO,EAAE,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;YAC7D,gBAAgB;YAChB,gBAAgB;SACjB,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,28 @@
import type { JSONSchema } from '../../jsonSchema';
import { SchemaDialect } from '../../jsonSchema';
import type { ASTNode, ArrayASTNode, ObjectASTNode } from '../../jsonASTTypes';
import { Draft07Validator } from './draft07Validator';
import { ValidationResult } from './baseValidator';
import type { ISchemaCollector, Options } from './baseValidator';
export declare class Draft2019Validator extends Draft07Validator {
protected getCurrentDialect(): SchemaDialect;
/**
* Keyword: contains + minContains/maxContains
*
* Draft-07 behavior: contains must match at least 1 item.
* Draft-2019-09 behavior: minContains/maxContains constrain how many matches are required/allowed.
*/
protected applyContains(node: ArrayASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, _matchingSchemas: ISchemaCollector, options: Options): void;
/**
* Keyword: dependentRequired + dependentSchemas.
*/
protected applyDependencies(node: ObjectASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, matchingSchemas: ISchemaCollector, options: Options, seenKeys: Record<string, ASTNode>): void;
/**
* Keyword: unevaluatedProperties
*/
protected applyUnevaluatedProperties(node: ObjectASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, matchingSchemas: ISchemaCollector, options: Options, seenKeys?: Record<string, ASTNode>): void;
/**
* Keyword: unevaluatedItems
*/
protected applyUnevaluatedItems(node: ArrayASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, matchingSchemas: ISchemaCollector, options: Options): void;
}
@@ -0,0 +1,224 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) IBM Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { SchemaDialect } from '../../jsonSchema';
import { isNumber } from '../../utils/objects';
import * as l10n from '@vscode/l10n';
import { DiagnosticSeverity } from 'vscode-languageserver-types';
import { ErrorCode } from 'vscode-json-languageservice';
import { Draft07Validator } from './draft07Validator';
import { ValidationResult, asSchema } from './baseValidator';
export class Draft2019Validator extends Draft07Validator {
getCurrentDialect() {
return SchemaDialect.draft2019;
}
/**
* Keyword: contains + minContains/maxContains
*
* Draft-07 behavior: contains must match at least 1 item.
* Draft-2019-09 behavior: minContains/maxContains constrain how many matches are required/allowed.
*/
applyContains(node, schema, originalSchema, validationResult, _matchingSchemas, options) {
const containsSchema = asSchema(schema.contains);
if (!containsSchema)
return;
const minContainsRaw = schema.minContains;
const maxContainsRaw = schema.maxContains;
const minContains = isNumber(minContainsRaw) ? minContainsRaw : 1;
const maxContains = isNumber(maxContainsRaw) ? maxContainsRaw : undefined;
let matchCount = 0;
const items = (node.items ?? []);
for (const item of items) {
const itemValidationResult = new ValidationResult(options.isKubernetes);
this.validateNode(item, containsSchema, schema, itemValidationResult, this.getNoOpCollector(), options);
if (!itemValidationResult.hasProblems()) {
matchCount++;
if (maxContains !== undefined && matchCount > maxContains) {
break;
}
}
}
if (matchCount < minContains) {
validationResult.problems.push({
location: { offset: node.offset, length: node.length },
severity: DiagnosticSeverity.Warning,
message: schema.errorMessage || l10n.t('Array has too few items matching "contains". Expected {0} or more.', minContains),
source: this.getSchemaSource(schema, originalSchema),
schemaUri: this.getSchemaUri(schema, originalSchema),
});
}
if (maxContains !== undefined && matchCount > maxContains) {
validationResult.problems.push({
location: { offset: node.offset, length: node.length },
severity: DiagnosticSeverity.Warning,
message: schema.errorMessage || l10n.t('Array has too many items matching "contains". Expected {0} or fewer.', maxContains),
source: this.getSchemaSource(schema, originalSchema),
schemaUri: this.getSchemaUri(schema, originalSchema),
});
}
}
/**
* Keyword: dependentRequired + dependentSchemas.
*/
applyDependencies(node, schema, originalSchema, validationResult, matchingSchemas, options, seenKeys) {
// keep draft-07 dependencies support
super.applyDependencies(node, schema, originalSchema, validationResult, matchingSchemas, options, seenKeys);
const dependentRequired = schema.dependentRequired;
if (dependentRequired && typeof dependentRequired === 'object') {
for (const prop of Object.keys(dependentRequired)) {
if (!seenKeys[prop])
continue;
const requiredProps = dependentRequired[prop];
if (!Array.isArray(requiredProps))
continue;
for (const requiredProp of requiredProps) {
if (!seenKeys[requiredProp]) {
validationResult.problems.push({
location: { offset: node.offset, length: node.length },
severity: DiagnosticSeverity.Warning,
message: l10n.t('Object is missing property {0} required by property {1}.', requiredProp, prop),
source: this.getSchemaSource(schema, originalSchema),
schemaUri: this.getSchemaUri(schema, originalSchema),
});
}
else {
validationResult.propertiesValueMatches++;
}
}
}
}
const dependentSchemas = schema.dependentSchemas;
if (dependentSchemas && typeof dependentSchemas === 'object') {
for (const prop of Object.keys(dependentSchemas)) {
if (!seenKeys[prop])
continue;
const depSchema = asSchema(dependentSchemas[prop]);
if (!depSchema)
continue;
const depValidationResult = new ValidationResult(options.isKubernetes);
this.validateNode(node, depSchema, schema, depValidationResult, matchingSchemas, options);
validationResult.mergePropertyMatch(depValidationResult);
validationResult.mergeEnumValues(depValidationResult);
}
}
}
/**
* Keyword: unevaluatedProperties
*/
applyUnevaluatedProperties(node, schema, originalSchema, validationResult, matchingSchemas, options, seenKeys) {
const unevaluated = schema.unevaluatedProperties;
if (unevaluated === undefined)
return;
if (!seenKeys)
return;
// ensure evaluatedProperties exists
validationResult.evaluatedProperties ?? (validationResult.evaluatedProperties = new Set());
// remaining = properties not evaluated by properties/patternProperties/additionalProperties
const remaining = Object.keys(seenKeys).filter((name) => !validationResult.evaluatedProperties?.has(name));
if (remaining.length === 0)
return;
// unevaluatedProperties: false => forbid remaining properties
if (unevaluated === false) {
for (const propName of remaining) {
const child = seenKeys[propName];
if (!child)
continue;
const propertyNode = child.type === 'property' ? child : child.parent;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const keyNode = propertyNode.keyNode;
if (!keyNode)
continue;
validationResult.problems.push({
location: { offset: keyNode.offset, length: keyNode.length },
severity: DiagnosticSeverity.Warning,
code: ErrorCode.PropertyExpected,
message: schema.errorMessage || l10n.t('Property {0} is not allowed.', propName),
source: this.getSchemaSource(schema, originalSchema),
schemaUri: this.getSchemaUri(schema, originalSchema),
});
validationResult.evaluatedProperties?.add(propName);
}
return;
}
// unevaluatedProperties: true => allow anything remaining, but mark evaluated
if (unevaluated === true) {
for (const propName of remaining) {
validationResult.evaluatedProperties?.add(propName);
}
return;
}
// unevaluatedProperties: <schema> => validate value of each remaining property
const unevaluatedSchema = asSchema(unevaluated);
if (!unevaluatedSchema)
return;
for (const propName of remaining) {
const child = seenKeys[propName];
if (!child)
continue;
const valueNode = child.type === 'property' ? child.valueNode : child;
if (!valueNode)
continue;
const subResult = new ValidationResult(options.isKubernetes);
this.validateNode(valueNode, unevaluatedSchema, schema, subResult, matchingSchemas, options);
validationResult.mergePropertyMatch(subResult);
validationResult.mergeEnumValues(subResult);
validationResult.evaluatedProperties?.add(propName);
}
}
/**
* Keyword: unevaluatedItems
*/
applyUnevaluatedItems(node, schema, originalSchema, validationResult, matchingSchemas, options) {
const unevaluated = schema.unevaluatedItems;
if (unevaluated === undefined)
return;
const items = (node.items ?? []);
if (items.length === 0)
return;
const evaluated = validationResult.getEvaluatedItems(node);
const remaining = [];
for (let i = 0; i < items.length; i++) {
if (!evaluated.has(i))
remaining.push(i);
}
if (remaining.length === 0)
return;
// unevaluatedItems: false => forbid remaining indices
if (unevaluated === false) {
for (const idx of remaining) {
const item = items[idx];
validationResult.problems.push({
location: { offset: item.offset, length: item.length || 1 },
severity: DiagnosticSeverity.Warning,
code: ErrorCode.PropertyExpected,
message: schema.errorMessage || l10n.t('Array has too many items according to schema. Expected {0} or fewer.', idx),
source: this.getSchemaSource(schema, originalSchema),
schemaUri: this.getSchemaUri(schema, originalSchema),
});
evaluated.add(idx);
}
return;
}
// unevaluatedItems: true => allow everything remaining, but mark evaluated
if (unevaluated === true) {
for (const idx of remaining)
evaluated.add(idx);
return;
}
// unevaluatedItems: <schema> => validate remaining items against that schema
const unevaluatedSchema = asSchema(unevaluated);
if (!unevaluatedSchema)
return;
for (const idx of remaining) {
const item = items[idx];
const subResult = new ValidationResult(options.isKubernetes);
// validate the item node with the unevaluatedItems subschema
this.validateNode(item, unevaluatedSchema, schema, subResult, matchingSchemas, options);
validationResult.merge(subResult);
validationResult.mergeEnumValues(subResult);
evaluated.add(idx);
}
}
}
//# sourceMappingURL=draft2019Validator.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,17 @@
import type { JSONSchema } from '../../jsonSchema';
import { SchemaDialect } from '../../jsonSchema';
import type { ArrayASTNode } from '../../jsonASTTypes';
import { Draft2019Validator } from './draft2019Validator';
import type { ISchemaCollector, Options } from './baseValidator';
import { ValidationResult } from './baseValidator';
export declare class Draft2020Validator extends Draft2019Validator {
protected getCurrentDialect(): SchemaDialect;
/**
* Keyword: prefixItems + items
*/
protected validateArrayNode(node: ArrayASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, matchingSchemas: ISchemaCollector, options: Options): void;
/**
* Draft 2020-12: contains keyword affects the unevaluatedItems keyword
*/
protected applyContains(node: ArrayASTNode, schema: JSONSchema, originalSchema: JSONSchema, validationResult: ValidationResult, _matchingSchemas: ISchemaCollector, options: Options): void;
}
@@ -0,0 +1,126 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) IBM Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { SchemaDialect } from '../../jsonSchema';
import { isNumber } from '../../utils/objects';
import * as l10n from '@vscode/l10n';
import { DiagnosticSeverity } from 'vscode-languageserver-types';
import { Draft2019Validator } from './draft2019Validator';
import { ValidationResult, asSchema } from './baseValidator';
export class Draft2020Validator extends Draft2019Validator {
getCurrentDialect() {
return SchemaDialect.draft2020;
}
/**
* Keyword: prefixItems + items
*/
validateArrayNode(node, schema, originalSchema, validationResult, matchingSchemas, options) {
const items = (node.items ?? []);
// prefixItems/items/contains contribute to evaluatedItems
const evaluatedItems = validationResult.getEvaluatedItems(node);
const prefixItems = schema.prefixItems;
// validate prefixItems
if (Array.isArray(prefixItems)) {
const limit = Math.min(prefixItems.length, items.length);
for (let i = 0; i < limit; i++) {
const subSchema = asSchema(prefixItems[i]);
if (!subSchema) {
evaluatedItems.add(i);
continue;
}
const itemValidationResult = new ValidationResult(options.isKubernetes);
this.validateNode(items[i], subSchema, schema, itemValidationResult, matchingSchemas, options);
validationResult.mergePropertyMatch(itemValidationResult, false);
validationResult.mergeEnumValues(itemValidationResult);
// mark as evaluated even if invalid (avoids duplicate unevaluatedItems noise)
evaluatedItems.add(i);
}
}
// validate remaining items against items
const itemsKeyword = schema.items;
const prefixLen = Array.isArray(prefixItems) ? prefixItems.length : 0;
if (items.length > prefixLen) {
if (itemsKeyword === false) {
// "items": false => no items allowed beyond prefixItems
validationResult.problems.push({
location: { offset: node.offset, length: node.length },
severity: DiagnosticSeverity.Warning,
message: l10n.t('Array has too many items according to schema. Expected {0} or fewer.', prefixLen),
source: this.getSchemaSource(schema, originalSchema),
schemaUri: this.getSchemaUri(schema, originalSchema),
});
// mark these as evaluated by "items": false (so unevaluatedItems doesn't also complain)
for (let i = prefixLen; i < items.length; i++) {
evaluatedItems.add(i);
}
}
else {
const tailSchema = asSchema(itemsKeyword);
// if items is undefined, there's no constraint for remaining items and they remain unevaluated
if (tailSchema) {
for (let i = prefixLen; i < items.length; i++) {
const itemValidationResult = new ValidationResult(options.isKubernetes);
this.validateNode(items[i], tailSchema, schema, itemValidationResult, matchingSchemas, options);
validationResult.mergePropertyMatch(itemValidationResult, false);
validationResult.mergeEnumValues(itemValidationResult);
// mark as evaluated even if invalid (avoids duplicate unevaluatedItems noise)
evaluatedItems.add(i);
}
}
}
}
// contains enforces min/max and marks matching indices as evaluated
this.applyContains(node, schema, originalSchema, validationResult, matchingSchemas, options);
// generic array keywords
this.applyArrayLength(node, schema, originalSchema, validationResult, options);
this.applyUniqueItems(node, schema, originalSchema, validationResult);
}
/**
* Draft 2020-12: contains keyword affects the unevaluatedItems keyword
*/
applyContains(node, schema, originalSchema, validationResult, _matchingSchemas, options) {
const containsSchema = asSchema(schema.contains);
if (!containsSchema)
return;
const items = (node.items ?? []);
const minContainsRaw = schema.minContains;
const maxContainsRaw = schema.maxContains;
const minContains = isNumber(minContainsRaw) ? minContainsRaw : 1;
const maxContains = isNumber(maxContainsRaw) ? maxContainsRaw : undefined;
let matchCount = 0;
// ensure evaluatedItems exists
const evaluatedItems = validationResult.getEvaluatedItems(node);
for (let i = 0; i < items.length; i++) {
const itemValidationResult = new ValidationResult(options.isKubernetes);
this.validateNode(items[i], containsSchema, schema, itemValidationResult, this.getNoOpCollector(), options);
if (!itemValidationResult.hasProblems()) {
// items that match contains are considered evaluated
evaluatedItems.add(i);
matchCount++;
if (maxContains !== undefined && matchCount > maxContains) {
break;
}
}
}
if (matchCount < minContains) {
validationResult.problems.push({
location: { offset: node.offset, length: node.length },
severity: DiagnosticSeverity.Warning,
message: schema.errorMessage || l10n.t('Array has too few items matching "contains". Expected {0} or more.', minContains),
source: this.getSchemaSource(schema, originalSchema),
schemaUri: this.getSchemaUri(schema, originalSchema),
});
}
if (maxContains !== undefined && matchCount > maxContains) {
validationResult.problems.push({
location: { offset: node.offset, length: node.length },
severity: DiagnosticSeverity.Warning,
message: schema.errorMessage || l10n.t('Array has too many items matching "contains". Expected {0} or fewer.', maxContains),
source: this.getSchemaSource(schema, originalSchema),
schemaUri: this.getSchemaUri(schema, originalSchema),
});
}
}
}
//# sourceMappingURL=draft2020Validator.js.map
@@ -0,0 +1 @@
{"version":3,"file":"draft2020Validator.js","sourceRoot":"","sources":["../../../../../src/languageservice/parser/schemaValidation/draft2020Validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
import { SchemaDialect } from '../../jsonSchema';
import { BaseValidator } from './baseValidator';
export declare function getValidator(dialect: SchemaDialect): BaseValidator;
@@ -0,0 +1,24 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) IBM Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { SchemaDialect } from '../../jsonSchema';
import { Draft04Validator } from './draft04Validator';
import { Draft07Validator } from './draft07Validator';
import { Draft2019Validator } from './draft2019Validator';
import { Draft2020Validator } from './draft2020Validator';
export function getValidator(dialect) {
switch (dialect) {
case SchemaDialect.draft04:
return new Draft04Validator();
case SchemaDialect.draft07:
return new Draft07Validator();
case SchemaDialect.draft2019:
return new Draft2019Validator();
case SchemaDialect.draft2020:
return new Draft2020Validator();
default:
return new Draft07Validator(); // fallback
}
}
//# sourceMappingURL=validatorFactory.js.map
@@ -0,0 +1 @@
{"version":3,"file":"validatorFactory.js","sourceRoot":"","sources":["../../../../../src/languageservice/parser/schemaValidation/validatorFactory.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,UAAU,YAAY,CAAC,OAAsB;IACjD,QAAQ,OAAO,EAAE;QACf,KAAK,aAAa,CAAC,OAAO;YACxB,OAAO,IAAI,gBAAgB,EAAE,CAAC;QAChC,KAAK,aAAa,CAAC,OAAO;YACxB,OAAO,IAAI,gBAAgB,EAAE,CAAC;QAChC,KAAK,aAAa,CAAC,SAAS;YAC1B,OAAO,IAAI,kBAAkB,EAAE,CAAC;QAClC,KAAK,aAAa,CAAC,SAAS;YAC1B,OAAO,IAAI,kBAAkB,EAAE,CAAC;QAClC;YACE,OAAO,IAAI,gBAAgB,EAAE,CAAC,CAAC,WAAW;KAC7C;AACH,CAAC"}
@@ -0,0 +1,71 @@
import { TextDocument } from 'vscode-languageserver-textdocument';
import { JSONDocument } from './jsonDocument';
import { Document, LineCounter } from 'yaml';
import { ASTNode, YamlNode } from '../jsonASTTypes';
import { ParserOptions } from './yamlParser07';
import { YAMLDocDiagnostic } from '../utils/parseUtils';
import { TextBuffer } from '../utils/textBuffer';
import { Token } from 'yaml/dist/parse/cst';
/**
* These documents are collected into a final YAMLDocument
* and passed to the `parseYAML` caller.
*/
export declare class SingleYAMLDocument extends JSONDocument {
private lineCounter;
private _internalDocument;
root: ASTNode;
currentDocIndex: number;
private _lineComments;
constructor(lineCounter?: LineCounter);
/**
* Create a deep copy of this document
*/
clone(): SingleYAMLDocument;
private collectLineComments;
/**
* Updates the internal AST tree of the object
* from the internal node. This is call whenever the
* internalDocument is set but also can be called to
* reflect any changes on the underlying document
* without setting the internalDocument explicitly.
*/
updateFromInternalDocument(): void;
set internalDocument(document: Document);
get internalDocument(): Document;
get lineComments(): string[];
set lineComments(val: string[]);
get errors(): YAMLDocDiagnostic[];
get warnings(): YAMLDocDiagnostic[];
getNodeFromPosition(positionOffset: number, textBuffer: TextBuffer, configuredIndentation?: number): [YamlNode | undefined, boolean];
findClosestNode(offset: number, textBuffer: TextBuffer, configuredIndentation?: number): YamlNode;
private getProperParentByIndentation;
getParent(node: YamlNode): YamlNode | undefined;
}
/**
* Contains the SingleYAMLDocuments, to be passed
* to the `parseYAML` caller.
*/
export declare class YAMLDocument {
documents: SingleYAMLDocument[];
tokens: Token[];
private errors;
private warnings;
constructor(documents: SingleYAMLDocument[], tokens: Token[]);
}
export declare class YamlDocuments {
private cache;
/**
* Get cached YAMLDocument
* @param document TextDocument to parse
* @param parserOptions YAML parserOptions
* @param addRootObject if true and document is empty add empty object {} to force schema usage
* @returns the YAMLDocument
*/
getYamlDocument(document: TextDocument, parserOptions?: ParserOptions, addRootObject?: boolean): YAMLDocument;
/**
* For test purpose only!
*/
clear(): void;
private ensureCache;
}
export declare const yamlDocumentsCache: YamlDocuments;
@@ -0,0 +1,258 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { JSONDocument } from './jsonDocument';
import { isNode, isPair, isScalar, visit } from 'yaml';
import { defaultOptions, parse as parseYAML } from './yamlParser07';
import { ErrorCode } from 'vscode-json-languageservice';
import { convertAST } from './ast-converter';
import { isArrayEqual } from '../utils/arrUtils';
import { getParent } from '../utils/yamlAstUtils';
import { getIndentation } from '../utils/strings';
/**
* These documents are collected into a final YAMLDocument
* and passed to the `parseYAML` caller.
*/
export class SingleYAMLDocument extends JSONDocument {
constructor(lineCounter) {
super(null, []);
this.lineCounter = lineCounter;
}
/**
* Create a deep copy of this document
*/
clone() {
const copy = new SingleYAMLDocument(this.lineCounter);
copy.isKubernetes = this.isKubernetes;
copy.disableAdditionalProperties = this.disableAdditionalProperties;
copy.uri = this.uri;
copy.currentDocIndex = this.currentDocIndex;
copy._lineComments = this.lineComments.slice();
// this will re-create root node
copy.internalDocument = this._internalDocument.clone();
return copy;
}
collectLineComments() {
this._lineComments = [];
if (this._internalDocument.commentBefore) {
const comments = this._internalDocument.commentBefore.split('\n');
comments.forEach((comment) => this._lineComments.push(`#${comment}`));
}
visit(this.internalDocument, (_key, node) => {
if (node?.commentBefore) {
const comments = node?.commentBefore.split('\n');
comments.forEach((comment) => this._lineComments.push(`#${comment}`));
}
if (node?.comment) {
this._lineComments.push(`#${node.comment}`);
}
});
if (this._internalDocument.comment) {
this._lineComments.push(`#${this._internalDocument.comment}`);
}
}
/**
* Updates the internal AST tree of the object
* from the internal node. This is call whenever the
* internalDocument is set but also can be called to
* reflect any changes on the underlying document
* without setting the internalDocument explicitly.
*/
updateFromInternalDocument() {
this.root = convertAST(null, this._internalDocument.contents, this._internalDocument, this.lineCounter);
}
set internalDocument(document) {
this._internalDocument = document;
this.updateFromInternalDocument();
}
get internalDocument() {
return this._internalDocument;
}
get lineComments() {
if (!this._lineComments) {
this.collectLineComments();
}
return this._lineComments;
}
set lineComments(val) {
this._lineComments = val;
}
get errors() {
return this.internalDocument.errors.map(YAMLErrorToYamlDocDiagnostics);
}
get warnings() {
return this.internalDocument.warnings.map(YAMLErrorToYamlDocDiagnostics);
}
getNodeFromPosition(positionOffset, textBuffer, configuredIndentation) {
const position = textBuffer.getPosition(positionOffset);
const lineContent = textBuffer.getLineContent(position.line);
if (lineContent.trim().length === 0) {
return [this.findClosestNode(positionOffset, textBuffer, configuredIndentation), true];
}
const textAfterPosition = lineContent.substring(position.character);
const spacesAfterPositionMatch = textAfterPosition.match(/^([ ]+)\n?$/);
const areOnlySpacesAfterPosition = !!spacesAfterPositionMatch;
const countOfSpacesAfterPosition = spacesAfterPositionMatch?.[1].length;
let closestNode;
visit(this.internalDocument, (key, node) => {
if (!node) {
return;
}
const range = node.range;
if (!range) {
return;
}
const isNullNodeOnTheLine = () => areOnlySpacesAfterPosition &&
positionOffset + countOfSpacesAfterPosition === range[2] &&
isScalar(node) &&
node.value === null;
if ((range[0] <= positionOffset && range[1] >= positionOffset) || isNullNodeOnTheLine()) {
closestNode = node;
}
else {
return visit.SKIP;
}
});
return [closestNode, false];
}
findClosestNode(offset, textBuffer, configuredIndentation) {
let offsetDiff = this.internalDocument.range[2];
let maxOffset = this.internalDocument.range[0];
let closestNode;
visit(this.internalDocument, (key, node) => {
if (!node) {
return;
}
const range = node.range;
if (!range) {
return;
}
const diff = range[1] - offset;
if (maxOffset <= range[0] && diff <= 0 && Math.abs(diff) <= offsetDiff) {
offsetDiff = Math.abs(diff);
maxOffset = range[0];
closestNode = node;
}
});
const position = textBuffer.getPosition(offset);
const lineContent = textBuffer.getLineContent(position.line);
const indentation = getIndentation(lineContent, position.character);
if (isScalar(closestNode) && closestNode.value === null) {
return closestNode;
}
if (indentation === position.character) {
closestNode = this.getProperParentByIndentation(indentation, closestNode, textBuffer, '', configuredIndentation);
}
return closestNode;
}
getProperParentByIndentation(indentation, node, textBuffer, currentLine, configuredIndentation, rootParent) {
if (!node) {
return this.internalDocument.contents;
}
configuredIndentation = !configuredIndentation ? 2 : configuredIndentation;
if (isNode(node) && node.range) {
const position = textBuffer.getPosition(node.range[0]);
const lineContent = textBuffer.getLineContent(position.line);
currentLine = currentLine === '' ? lineContent.trim() : currentLine;
if (currentLine.startsWith('-') && indentation === configuredIndentation && currentLine === lineContent.trim()) {
position.character += indentation;
}
if (position.character > indentation && position.character > 0) {
const parent = this.getParent(node);
if (parent) {
return this.getProperParentByIndentation(indentation, parent, textBuffer, currentLine, configuredIndentation, rootParent);
}
}
else if (position.character < indentation) {
const parent = this.getParent(node);
if (isPair(parent) && isNode(parent.value)) {
return parent.value;
}
else if (isPair(rootParent) && isNode(rootParent.value)) {
return rootParent.value;
}
}
else {
return node;
}
}
else if (isPair(node)) {
rootParent = node;
const parent = this.getParent(node);
return this.getProperParentByIndentation(indentation, parent, textBuffer, currentLine, configuredIndentation, rootParent);
}
return node;
}
getParent(node) {
return getParent(this.internalDocument, node);
}
}
/**
* Contains the SingleYAMLDocuments, to be passed
* to the `parseYAML` caller.
*/
export class YAMLDocument {
constructor(documents, tokens) {
this.documents = documents;
this.tokens = tokens;
this.errors = [];
this.warnings = [];
}
}
export class YamlDocuments {
constructor() {
// a mapping of URIs to cached documents
this.cache = new Map();
}
/**
* Get cached YAMLDocument
* @param document TextDocument to parse
* @param parserOptions YAML parserOptions
* @param addRootObject if true and document is empty add empty object {} to force schema usage
* @returns the YAMLDocument
*/
getYamlDocument(document, parserOptions, addRootObject = false) {
this.ensureCache(document, parserOptions ?? defaultOptions, addRootObject);
return this.cache.get(document.uri).document;
}
/**
* For test purpose only!
*/
clear() {
this.cache.clear();
}
ensureCache(document, parserOptions, addRootObject) {
const key = document.uri;
if (!this.cache.has(key)) {
this.cache.set(key, { version: -1, document: new YAMLDocument([], []), parserOptions: defaultOptions });
}
const cacheEntry = this.cache.get(key);
if (cacheEntry.version !== document.version ||
(parserOptions.customTags && !isArrayEqual(cacheEntry.parserOptions.customTags, parserOptions.customTags))) {
let text = document.getText();
// if text is contains only whitespace wrap all text in object to force schema selection
if (addRootObject && !/\S/.test(text)) {
text = `{${text}}`;
}
const doc = parseYAML(text, parserOptions, document);
cacheEntry.document = doc;
cacheEntry.version = document.version;
cacheEntry.parserOptions = parserOptions;
}
}
}
export const yamlDocumentsCache = new YamlDocuments();
function YAMLErrorToYamlDocDiagnostics(error) {
return {
message: error.message,
location: {
start: error.pos[0],
end: error.pos[1],
toLineEnd: true,
},
severity: 1,
code: ErrorCode.Undefined,
};
}
//# sourceMappingURL=yaml-documents.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
import { YAMLDocument, SingleYAMLDocument } from './yaml-documents';
import { TextDocument } from 'vscode-languageserver-textdocument';
export { YAMLDocument, SingleYAMLDocument };
export type YamlVersion = '1.1' | '1.2';
export interface ParserOptions {
customTags: string[];
yamlVersion: YamlVersion;
}
export declare const defaultOptions: ParserOptions;
/**
* `yaml-ast-parser-custom-tags` parses the AST and
* returns YAML AST nodes, which are then formatted
* for consumption via the language server.
*/
export declare function parse(text: string, parserOptions?: ParserOptions, document?: TextDocument): YAMLDocument;
@@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Copyright (c) Adam Voss. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Parser, Composer, LineCounter } from 'yaml';
import { YAMLDocument, SingleYAMLDocument } from './yaml-documents';
import { getCustomTags } from './custom-tag-provider';
import { TextBuffer } from '../utils/textBuffer';
export { YAMLDocument, SingleYAMLDocument };
export const defaultOptions = {
customTags: [],
yamlVersion: '1.2',
};
/**
* `yaml-ast-parser-custom-tags` parses the AST and
* returns YAML AST nodes, which are then formatted
* for consumption via the language server.
*/
export function parse(text, parserOptions = defaultOptions, document) {
const options = {
strict: false,
customTags: getCustomTags(parserOptions.customTags),
version: parserOptions.yamlVersion ?? defaultOptions.yamlVersion,
keepSourceTokens: true,
};
const composer = new Composer(options);
const lineCounter = new LineCounter();
let isLastLineEmpty = false;
if (document) {
const textBuffer = new TextBuffer(document);
const position = textBuffer.getPosition(text.length);
const lineContent = textBuffer.getLineContent(position.line);
isLastLineEmpty = lineContent.trim().length === 0;
}
const parser = isLastLineEmpty ? new Parser() : new Parser(lineCounter.addNewLine);
const tokens = parser.parse(text);
const tokensArr = Array.from(tokens);
const docs = composer.compose(tokensArr, true, text.length);
// Generate the SingleYAMLDocs from the AST nodes
const yamlDocs = Array.from(docs, (doc) => parsedDocToSingleYAMLDocument(doc, lineCounter));
// Consolidate the SingleYAMLDocs
return new YAMLDocument(yamlDocs, tokensArr);
}
function parsedDocToSingleYAMLDocument(parsedDoc, lineCounter) {
const syd = new SingleYAMLDocument(lineCounter);
syd.internalDocument = parsedDoc;
return syd;
}
//# sourceMappingURL=yamlParser07.js.map
@@ -0,0 +1 @@
{"version":3,"file":"yamlParser07.js","sourceRoot":"","sources":["../../../../src/languageservice/parser/yamlParser07.ts"],"names":[],"mappings":"AAAA;;;;gGAIgG;AAEhG,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAY,WAAW,EAAgD,MAAM,MAAM,CAAC;AAC7G,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,CAAC;AAO5C,MAAM,CAAC,MAAM,cAAc,GAAkB;IAC3C,UAAU,EAAE,EAAE;IACd,WAAW,EAAE,KAAK;CACnB,CAAC;AACF;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAC,IAAY,EAAE,gBAA+B,cAAc,EAAE,QAAuB;IACxG,MAAM,OAAO,GAAmD;QAC9D,MAAM,EAAE,KAAK;QACb,UAAU,EAAE,aAAa,CAAC,aAAa,CAAC,UAAU,CAAC;QACnD,OAAO,EAAE,aAAa,CAAC,WAAW,IAAI,cAAc,CAAC,WAAW;QAChE,gBAAgB,EAAE,IAAI;KACvB,CAAC;IACF,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;IACtC,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,IAAI,QAAQ,EAAE;QACZ,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrD,MAAM,WAAW,GAAG,UAAU,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC7D,eAAe,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC;KACnD;IACD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IACnF,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5D,iDAAiD;IACjD,MAAM,QAAQ,GAAyB,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,6BAA6B,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC;IAElH,iCAAiC;IACjC,OAAO,IAAI,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,6BAA6B,CAAC,SAAmB,EAAE,WAAwB;IAClF,MAAM,GAAG,GAAG,IAAI,kBAAkB,CAAC,WAAW,CAAC,CAAC;IAChD,GAAG,CAAC,gBAAgB,GAAG,SAAS,CAAC;IACjC,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,23 @@
import { SingleYAMLDocument } from '../parser/yamlParser07';
import { JSONDocument } from '../parser/jsonDocument';
import { ResolvedSchema } from 'vscode-json-languageservice/lib/umd/services/jsonSchemaService';
/**
* Retrieve schema by auto-detecting the Kubernetes GroupVersionKind (GVK) from the document.
* If there is no definition for the GVK in the main kubernetes schema,
* the schema is then retrieved from the CRD catalog.
* Public for testing purpose, not part of the API.
* @param doc
* @param crdCatalogURI The URL of the CRD catalog to retrieve the schema from
* @param kubernetesSchema The main kubernetes schema, if it includes a definition for the GVK it will be used
*/
export declare function autoDetectKubernetesSchemaFromDocument(doc: SingleYAMLDocument | JSONDocument, crdCatalogURI: string, kubernetesSchema: ResolvedSchema): string | undefined;
/**
* Retrieve the group, version and kind from the document.
* Public for testing purpose, not part of the API.
* @param doc
*/
export declare function getGroupVersionKindFromDocument(doc: SingleYAMLDocument | JSONDocument): {
group: string;
version: string;
kind: string;
} | undefined;
@@ -0,0 +1,74 @@
import { SingleYAMLDocument } from '../parser/yamlParser07';
/**
* Retrieve schema by auto-detecting the Kubernetes GroupVersionKind (GVK) from the document.
* If there is no definition for the GVK in the main kubernetes schema,
* the schema is then retrieved from the CRD catalog.
* Public for testing purpose, not part of the API.
* @param doc
* @param crdCatalogURI The URL of the CRD catalog to retrieve the schema from
* @param kubernetesSchema The main kubernetes schema, if it includes a definition for the GVK it will be used
*/
export function autoDetectKubernetesSchemaFromDocument(doc, crdCatalogURI, kubernetesSchema) {
const res = getGroupVersionKindFromDocument(doc);
if (!res) {
return undefined;
}
const { group, version, kind } = res;
if (!group || !version || !kind) {
return undefined;
}
const k8sSchema = kubernetesSchema.schema;
const kubernetesBuildIns = (k8sSchema.oneOf || [])
.map((s) => {
if (typeof s === 'boolean') {
return undefined;
}
return s._$ref || s.$ref;
})
.filter((ref) => ref)
.map((ref) => ref.replace('_definitions.json#/definitions/', '').toLowerCase());
const groupWithoutK8sIO = group.replace('.k8s.io', '');
const k8sTypeName = `io.k8s.api.${groupWithoutK8sIO.toLowerCase()}.${version.toLowerCase()}.${kind.toLowerCase()}`;
if (kubernetesBuildIns.includes(k8sTypeName)) {
return undefined;
}
if (k8sTypeName.includes('openshift.io')) {
return `${crdCatalogURI}/openshift/v4.15-strict/${kind.toLowerCase()}_${group.toLowerCase()}_${version.toLowerCase()}.json`;
}
const schemaURL = `${crdCatalogURI}/${group.toLowerCase()}/${kind.toLowerCase()}_${version.toLowerCase()}.json`;
return schemaURL;
}
/**
* Retrieve the group, version and kind from the document.
* Public for testing purpose, not part of the API.
* @param doc
*/
export function getGroupVersionKindFromDocument(doc) {
if (doc instanceof SingleYAMLDocument) {
try {
const rootJSON = doc.root.internalNode.toJSON();
if (!rootJSON) {
return undefined;
}
const groupVersion = rootJSON['apiVersion'];
if (!groupVersion) {
return undefined;
}
const [group, version] = groupVersion.split('/');
if (!group || !version) {
return undefined;
}
const kind = rootJSON['kind'];
if (!kind) {
return undefined;
}
return { group, version, kind };
}
catch (error) {
console.error('Error parsing YAML document:', error);
return undefined;
}
}
return undefined;
}
//# sourceMappingURL=crdUtil.js.map
@@ -0,0 +1 @@
{"version":3,"file":"crdUtil.js","sourceRoot":"","sources":["../../../../src/languageservice/services/crdUtil.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
import { SymbolInformation, DocumentSymbol } from 'vscode-languageserver-types';
import { YAMLSchemaService } from './yamlSchemaService';
import { DocumentSymbolsContext } from 'vscode-json-languageservice/lib/umd/jsonLanguageTypes';
import { TextDocument } from 'vscode-languageserver-textdocument';
import { Telemetry } from '../telemetry';
export declare class YAMLDocumentSymbols {
private readonly telemetry?;
private jsonDocumentSymbols;
constructor(schemaService: YAMLSchemaService, telemetry?: Telemetry);
findDocumentSymbols(document: TextDocument, context?: DocumentSymbolsContext): SymbolInformation[];
findHierarchicalDocumentSymbols(document: TextDocument, context?: DocumentSymbolsContext): DocumentSymbol[];
}
@@ -0,0 +1,67 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { JSONDocumentSymbols } from 'vscode-json-languageservice/lib/umd/services/jsonDocumentSymbols';
import { yamlDocumentsCache } from '../parser/yaml-documents';
import { isMap, isSeq } from 'yaml';
export class YAMLDocumentSymbols {
constructor(schemaService, telemetry) {
this.telemetry = telemetry;
this.jsonDocumentSymbols = new JSONDocumentSymbols(schemaService);
// override 'getKeyLabel' to handle complex mapping
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.jsonDocumentSymbols.getKeyLabel = (property) => {
const keyNode = property.keyNode.internalNode;
let name = '';
if (isMap(keyNode)) {
name = '{}';
}
else if (isSeq(keyNode)) {
name = '[]';
}
else {
name = keyNode.source;
}
return name;
};
}
findDocumentSymbols(document, context = { resultLimit: Number.MAX_VALUE }) {
let results = [];
try {
const doc = yamlDocumentsCache.getYamlDocument(document);
if (!doc || doc['documents'].length === 0) {
return null;
}
for (const yamlDoc of doc['documents']) {
if (yamlDoc.root) {
results = results.concat(this.jsonDocumentSymbols.findDocumentSymbols(document, yamlDoc, context));
}
}
}
catch (err) {
this.telemetry?.sendError('yaml.documentSymbols.error', err);
}
return results;
}
findHierarchicalDocumentSymbols(document, context = { resultLimit: Number.MAX_VALUE }) {
let results = [];
try {
const doc = yamlDocumentsCache.getYamlDocument(document);
if (!doc || doc['documents'].length === 0) {
return null;
}
for (const yamlDoc of doc['documents']) {
if (yamlDoc.root) {
results = results.concat(this.jsonDocumentSymbols.findDocumentSymbols2(document, yamlDoc, context));
}
}
}
catch (err) {
this.telemetry?.sendError('yaml.hierarchicalDocumentSymbols.error', err);
}
return results;
}
}
//# sourceMappingURL=documentSymbols.js.map
@@ -0,0 +1 @@
{"version":3,"file":"documentSymbols.js","sourceRoot":"","sources":["../../../../src/languageservice/services/documentSymbols.ts"],"names":[],"mappings":"AAAA;;;;gGAIgG;AAIhG,OAAO,EAAE,mBAAmB,EAAE,MAAM,kEAAkE,CAAC;AAGvG,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAQ,MAAM,MAAM,CAAC;AAE1C,MAAM,OAAO,mBAAmB;IAG9B,YACE,aAAgC,EACf,SAAqB;QAArB,cAAS,GAAT,SAAS,CAAY;QAEtC,IAAI,CAAC,mBAAmB,GAAG,IAAI,mBAAmB,CAAC,aAAa,CAAC,CAAC;QAElE,mDAAmD;QACnD,8DAA8D;QAC9D,IAAI,CAAC,mBAAmB,CAAC,WAAW,GAAG,CAAC,QAAa,EAAE,EAAE;YACvD,MAAM,OAAO,GAAS,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC;YACpD,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE;gBAClB,IAAI,GAAG,IAAI,CAAC;aACb;iBAAM,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE;gBACzB,IAAI,GAAG,IAAI,CAAC;aACb;iBAAM;gBACL,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;aACvB;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC;IACJ,CAAC;IAEM,mBAAmB,CACxB,QAAsB,EACtB,UAAkC,EAAE,WAAW,EAAE,MAAM,CAAC,SAAS,EAAE;QAEnE,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,IAAI;YACF,MAAM,GAAG,GAAG,kBAAkB,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;YACzD,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;gBACzC,OAAO,IAAI,CAAC;aACb;YAED,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,WAAW,CAAC,EAAE;gBACtC,IAAI,OAAO,CAAC,IAAI,EAAE;oBAChB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;iBACpG;aACF;SACF;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAC;SAC9D;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAEM,+BAA+B,CACpC,QAAsB,EACtB,UAAkC,EAAE,WAAW,EAAE,MAAM,CAAC,SAAS,EAAE;QAEnE,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,IAAI;YACF,MAAM,GAAG,GAAG,kBAAkB,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;YACzD,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;gBACzC,OAAO,IAAI,CAAC;aACb;YAED,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,WAAW,CAAC,EAAE;gBACtC,IAAI,OAAO,CAAC,IAAI,EAAE;oBAChB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,oBAAoB,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;iBACrG;aACF;SACF;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,wCAAwC,EAAE,GAAG,CAAC,CAAC;SAC1E;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
@@ -0,0 +1,9 @@
import { SingleYAMLDocument } from '../parser/yamlParser07';
import { JSONDocument } from '../parser/jsonDocument';
/**
* Retrieve schema if declared as modeline.
* Public for testing purpose, not part of the API.
* @param doc
*/
export declare function getSchemaFromModeline(doc: SingleYAMLDocument | JSONDocument): string;
export declare function isModeline(lineText: string): boolean;
@@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { SingleYAMLDocument } from '../parser/yamlParser07';
/**
* Retrieve schema if declared as modeline.
* Public for testing purpose, not part of the API.
* @param doc
*/
export function getSchemaFromModeline(doc) {
if (doc instanceof SingleYAMLDocument) {
const yamlLanguageServerModeline = doc.lineComments.find((lineComment) => {
return isModeline(lineComment);
});
if (yamlLanguageServerModeline != undefined) {
const schemaMatchs = yamlLanguageServerModeline.match(/\$schema=\S+/g);
if (schemaMatchs !== null && schemaMatchs.length >= 1) {
if (schemaMatchs.length >= 2) {
console.log('Several $schema attributes have been found on the yaml-language-server modeline. The first one will be picked.');
}
return schemaMatchs[0].substring('$schema='.length);
}
}
}
return undefined;
}
export function isModeline(lineText) {
const matchModeline = lineText.match(/^#\s+yaml-language-server\s*:/g);
return matchModeline !== null && matchModeline.length === 1;
}
//# sourceMappingURL=modelineUtil.js.map
@@ -0,0 +1 @@
{"version":3,"file":"modelineUtil.js","sourceRoot":"","sources":["../../../../src/languageservice/services/modelineUtil.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAG5D;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAsC;IAC1E,IAAI,GAAG,YAAY,kBAAkB,EAAE;QACrC,MAAM,0BAA0B,GAAG,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE;YACvE,OAAO,UAAU,CAAC,WAAW,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QACH,IAAI,0BAA0B,IAAI,SAAS,EAAE;YAC3C,MAAM,YAAY,GAAG,0BAA0B,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;YACvE,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,CAAC,MAAM,IAAI,CAAC,EAAE;gBACrD,IAAI,YAAY,CAAC,MAAM,IAAI,CAAC,EAAE;oBAC5B,OAAO,CAAC,GAAG,CACT,gHAAgH,CACjH,CAAC;iBACH;gBACD,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;aACrD;SACF;KACF;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACvE,OAAO,aAAa,KAAK,IAAI,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,12 @@
import { Connection, WorkspaceFolder } from 'vscode-languageserver';
import { URI } from 'vscode-uri';
import { WorkspaceContextService } from '../yamlLanguageService';
export interface FileSystem {
readFile(fsPath: string, encoding?: string): Promise<string>;
}
/**
* Handles schema content requests given the schema URI
* @param uri can be a local file, vscode request, http(s) request or a custom request
*/
export declare const schemaRequestHandler: (connection: Connection, uri: string, workspaceFolders: WorkspaceFolder[], workspaceRoot: URI, useVSCodeContentRequest: boolean, fs: FileSystem, isWeb: boolean) => Promise<string>;
export declare const workspaceContext: WorkspaceContextService;
@@ -0,0 +1,84 @@
import { join } from 'path';
import { getErrorStatusDescription, xhr } from 'request-light';
import * as URL from 'url';
import { RequestType } from 'vscode-languageserver';
import { URI } from 'vscode-uri';
import { CustomSchemaContentRequest, VSCodeContentRequest } from '../../requestTypes';
import { isRelativePath, relativeToAbsolutePath } from '../utils/paths';
// eslint-disable-next-line @typescript-eslint/no-namespace
var FSReadUri;
(function (FSReadUri) {
FSReadUri.type = new RequestType('fs/readUri');
})(FSReadUri || (FSReadUri = {}));
/**
* Handles schema content requests given the schema URI
* @param uri can be a local file, vscode request, http(s) request or a custom request
*/
export const schemaRequestHandler = async (connection, uri, workspaceFolders, workspaceRoot, useVSCodeContentRequest, fs, isWeb) => {
if (!uri) {
return Promise.reject('No schema specified');
}
// If the requested schema URI is a relative file path
// Convert it into a proper absolute path URI
if (isRelativePath(uri)) {
// HACK: the fs/readUri extension is only available with vscode-yaml,
// and this fix is specific to vscode-yaml on web, so don't use it in other cases
if (workspaceFolders.length === 1 && isWeb) {
const wsUri = URI.parse(workspaceFolders[0].uri);
const wsDirname = wsUri.path;
const modifiedUri = wsUri.with({ path: join(wsDirname, uri) });
try {
return connection.sendRequest(FSReadUri.type, modifiedUri.toString());
}
catch (e) {
connection.window.showErrorMessage(`failed to get content of '${modifiedUri}': ${e}`);
}
}
else {
uri = relativeToAbsolutePath(workspaceFolders, workspaceRoot, uri);
}
}
let scheme = URI.parse(uri).scheme.toLowerCase();
// test if uri is windows path, ie starts with 'c:\'
if (/^[a-z]:[\\/]/i.test(uri)) {
const winUri = URI.file(uri);
scheme = winUri.scheme.toLowerCase();
uri = winUri.toString();
}
// If the requested schema is a local file, read and return the file contents
if (scheme === 'file') {
const fsPath = URI.parse(uri).fsPath;
return fs.readFile(fsPath, 'UTF-8').catch(() => {
// If there was an error reading the file, return empty error message
// Otherwise return the file contents as a string
return '';
});
}
// HTTP(S) requests are sent and the response result is either the schema content or an error
if (scheme === 'http' || scheme === 'https') {
// If we are running inside of VSCode we need to make a content request. This content request
// will make it so that schemas behind VPN's will resolve correctly
if (useVSCodeContentRequest) {
return connection.sendRequest(VSCodeContentRequest.type, uri).then((responseText) => {
return responseText;
}, (error) => {
return Promise.reject(error.message);
});
}
// Send the HTTP(S) schema content request and return the result
const headers = { 'Accept-Encoding': 'gzip, deflate' };
return xhr({ url: uri, followRedirects: 5, headers }).then((response) => {
return response.responseText;
}, (error) => {
return Promise.reject(error.responseText || getErrorStatusDescription(error.status) || error.toString());
});
}
// Neither local file nor vscode, nor HTTP(S) schema request, so send it off as a custom request
return connection.sendRequest(CustomSchemaContentRequest.type, uri);
};
export const workspaceContext = {
resolveRelativePath: (relativePath, resource) => {
return URL.resolve(resource, relativePath);
},
};
//# sourceMappingURL=schemaRequestHandler.js.map
@@ -0,0 +1 @@
{"version":3,"file":"schemaRequestHandler.js","sourceRoot":"","sources":["../../../../src/languageservice/services/schemaRequestHandler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
import { TextDocument } from 'vscode-languageserver-textdocument';
import { Diagnostic } from 'vscode-languageserver-types';
import { SingleYAMLDocument } from '../../parser/yaml-documents';
import { AdditionalValidator } from './types';
export declare class MapKeyOrderValidator implements AdditionalValidator {
validate(document: TextDocument, yamlDoc: SingleYAMLDocument): Diagnostic[];
}
@@ -0,0 +1,35 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Diagnostic, DiagnosticSeverity, Range } from 'vscode-languageserver-types';
import { isMap, visit } from 'yaml';
export class MapKeyOrderValidator {
validate(document, yamlDoc) {
const result = [];
visit(yamlDoc.internalDocument, (key, node) => {
if (isMap(node)) {
for (let i = 1; i < node.items.length; i++) {
if (compare(node.items[i - 1], node.items[i]) > 0) {
const range = createRange(document, node.items[i - 1]);
result.push(Diagnostic.create(range, `Wrong ordering of key "${node.items[i - 1].key}" in mapping`, DiagnosticSeverity.Error, 'mapKeyOrder'));
break;
}
}
}
});
return result;
}
}
function createRange(document, node) {
const keySourceToken = node.key.srcToken;
const start = keySourceToken.offset;
const end = start + keySourceToken.source.length;
return Range.create(document.positionAt(start), document.positionAt(end));
}
function compare(thiz, that) {
const thatKey = String(that.key);
const thisKey = String(thiz.key);
return thisKey.localeCompare(thatKey);
}
//# sourceMappingURL=map-key-order.js.map
@@ -0,0 +1 @@
{"version":3,"file":"map-key-order.js","sourceRoot":"","sources":["../../../../../src/languageservice/services/validation/map-key-order.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAGhG,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AACpF,OAAO,EAAE,KAAK,EAAc,KAAK,EAAE,MAAM,MAAM,CAAC;AAKhD,MAAM,OAAO,oBAAoB;IAC/B,QAAQ,CAAC,QAAsB,EAAE,OAA2B;QAC1D,MAAM,MAAM,GAAG,EAAE,CAAC;QAElB,KAAK,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;YAC5C,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE;gBACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;oBAC1C,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;wBACjD,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;wBACvD,MAAM,CAAC,IAAI,CACT,UAAU,CAAC,MAAM,CACf,KAAK,EACL,0BAA0B,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,cAAc,EAC7D,kBAAkB,CAAC,KAAK,EACxB,aAAa,CACd,CACF,CAAC;wBACF,MAAM;qBACP;iBACF;aACF;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAED,SAAS,WAAW,CAAC,QAAsB,EAAE,IAAU;IACrD,MAAM,cAAc,GAAI,IAAI,CAAC,GAAY,CAAC,QAAuB,CAAC;IAClE,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC;IACpC,MAAM,GAAG,GAAG,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC;IACjD,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,OAAO,CAAC,IAAU,EAAE,IAAU;IACrC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjC,OAAO,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,6 @@
import { TextDocument } from 'vscode-languageserver-textdocument';
import { Diagnostic } from 'vscode-languageserver-types';
import { SingleYAMLDocument } from '../../parser/yaml-documents';
export interface AdditionalValidator {
validate(document: TextDocument, yamlDoc: SingleYAMLDocument): Diagnostic[];
}
@@ -0,0 +1,6 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export {};
//# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../src/languageservice/services/validation/types.ts"],"names":[],"mappings":"AAAA;;;gGAGgG"}
@@ -0,0 +1,8 @@
import { TextDocument } from 'vscode-languageserver-textdocument';
import { Diagnostic } from 'vscode-languageserver-types';
import { SingleYAMLDocument } from '../../parser/yaml-documents';
import { AdditionalValidator } from './types';
export declare class UnusedAnchorsValidator implements AdditionalValidator {
validate(document: TextDocument, yamlDoc: SingleYAMLDocument): Diagnostic[];
private getAnchorNode;
}
@@ -0,0 +1,91 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Diagnostic, DiagnosticSeverity, DiagnosticTag, Range } from 'vscode-languageserver-types';
import { isAlias, isCollection, isNode, isScalar, visit, CST } from 'yaml';
import { isCollectionItem } from '../../utils/yamlAstUtils';
import * as l10n from '@vscode/l10n';
export class UnusedAnchorsValidator {
validate(document, yamlDoc) {
const result = [];
const anchors = new Set();
const usedAnchors = new Set();
const unIdentifiedAlias = new Set();
const anchorParent = new Map();
visit(yamlDoc.internalDocument, (key, node, path) => {
if (!isNode(node)) {
return;
}
if ((isCollection(node) || isScalar(node)) && node.anchor) {
anchors.add(node);
anchorParent.set(node, path[path.length - 1]);
}
if (isAlias(node)) {
if (!node.resolve(yamlDoc.internalDocument)) {
unIdentifiedAlias.add(node);
}
else {
usedAnchors.add(node.resolve(yamlDoc.internalDocument));
}
}
});
for (const anchor of anchors) {
if (!usedAnchors.has(anchor)) {
const aToken = this.getAnchorNode(anchorParent.get(anchor), anchor);
if (aToken) {
const range = Range.create(document.positionAt(aToken.offset), document.positionAt(aToken.offset + aToken.source.length));
const warningDiagnostic = Diagnostic.create(range, l10n.t('Unused anchor "{0}"', aToken.source), DiagnosticSeverity.Information, 0);
warningDiagnostic.tags = [DiagnosticTag.Unnecessary];
result.push(warningDiagnostic);
}
}
}
unIdentifiedAlias.forEach((node) => {
const nodeRange = node.range;
if (nodeRange) {
const startOffset = nodeRange[0];
const endOffset = nodeRange[1];
const range = Range.create(document.positionAt(startOffset), document.positionAt(endOffset));
const warningDiagnostic = Diagnostic.create(range, l10n.t('Unresolved alias "{0}"', node.toString()), DiagnosticSeverity.Information, 0);
warningDiagnostic.tags = [DiagnosticTag.Unnecessary];
result.push(warningDiagnostic);
}
});
return result;
}
getAnchorNode(parentNode, node) {
if (parentNode && parentNode.srcToken) {
const token = parentNode.srcToken;
if (isCollectionItem(token)) {
return getAnchorFromCollectionItem(token);
}
else if (CST.isCollection(token)) {
for (const t of token.items) {
if (node.srcToken !== t.value)
continue;
const anchor = getAnchorFromCollectionItem(t);
if (anchor) {
return anchor;
}
}
}
}
return undefined;
}
}
function getAnchorFromCollectionItem(token) {
for (const t of token.start) {
if (t.type === 'anchor') {
return t;
}
}
if (token.sep && Array.isArray(token.sep)) {
for (const t of token.sep) {
if (t.type === 'anchor') {
return t;
}
}
}
}
//# sourceMappingURL=unused-anchors.js.map
@@ -0,0 +1 @@
{"version":3,"file":"unused-anchors.js","sourceRoot":"","sources":["../../../../../src/languageservice/services/validation/unused-anchors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
import { TextDocument } from 'vscode-languageserver-textdocument';
import { Diagnostic } from 'vscode-languageserver-types';
import { SingleYAMLDocument } from '../../parser/yaml-documents';
import { LanguageSettings } from '../../yamlLanguageService';
import { AdditionalValidator } from './types';
export declare class YAMLStyleValidator implements AdditionalValidator {
private forbidSequence;
private forbidMapping;
constructor(settings: LanguageSettings);
validate(document: TextDocument, yamlDoc: SingleYAMLDocument): Diagnostic[];
private getRangeOf;
}
@@ -0,0 +1,28 @@
import { Diagnostic, DiagnosticSeverity, Range } from 'vscode-languageserver-types';
import { isMap, isSeq, visit } from 'yaml';
import * as l10n from '@vscode/l10n';
export class YAMLStyleValidator {
constructor(settings) {
this.forbidMapping = settings.flowMapping === 'forbid';
this.forbidSequence = settings.flowSequence === 'forbid';
}
validate(document, yamlDoc) {
const result = [];
visit(yamlDoc.internalDocument, (key, node) => {
if (this.forbidMapping && isMap(node) && node.srcToken?.type === 'flow-collection') {
result.push(Diagnostic.create(this.getRangeOf(document, node.srcToken), l10n.t('Flow style mapping is forbidden'), DiagnosticSeverity.Error, 'flowMap'));
}
if (this.forbidSequence && isSeq(node) && node.srcToken?.type === 'flow-collection') {
result.push(Diagnostic.create(this.getRangeOf(document, node.srcToken), l10n.t('Flow style sequence is forbidden'), DiagnosticSeverity.Error, 'flowSeq'));
}
});
return result;
}
getRangeOf(document, node) {
const endOffset = node.end[0].offset;
let endPosition = document.positionAt(endOffset);
endPosition = { character: endPosition.character + 1, line: endPosition.line };
return Range.create(document.positionAt(node.start.offset), endPosition);
}
}
//# sourceMappingURL=yaml-style.js.map
@@ -0,0 +1 @@
{"version":3,"file":"yaml-style.js","sourceRoot":"","sources":["../../../../../src/languageservice/services/validation/yaml-style.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AACpF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAK3C,OAAO,KAAK,IAAI,MAAM,cAAc,CAAC;AAErC,MAAM,OAAO,kBAAkB;IAI7B,YAAY,QAA0B;QACpC,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,WAAW,KAAK,QAAQ,CAAC;QACvD,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAC,YAAY,KAAK,QAAQ,CAAC;IAC3D,CAAC;IACD,QAAQ,CAAC,QAAsB,EAAE,OAA2B;QAC1D,MAAM,MAAM,GAAG,EAAE,CAAC;QAClB,KAAK,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;YAC5C,IAAI,IAAI,CAAC,aAAa,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,KAAK,iBAAiB,EAAE;gBAClF,MAAM,CAAC,IAAI,CACT,UAAU,CAAC,MAAM,CACf,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,EACxC,IAAI,CAAC,CAAC,CAAC,iCAAiC,CAAC,EACzC,kBAAkB,CAAC,KAAK,EACxB,SAAS,CACV,CACF,CAAC;aACH;YACD,IAAI,IAAI,CAAC,cAAc,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,KAAK,iBAAiB,EAAE;gBACnF,MAAM,CAAC,IAAI,CACT,UAAU,CAAC,MAAM,CACf,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,EACxC,IAAI,CAAC,CAAC,CAAC,kCAAkC,CAAC,EAC1C,kBAAkB,CAAC,KAAK,EACxB,SAAS,CACV,CACF,CAAC;aACH;QACH,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,UAAU,CAAC,QAAsB,EAAE,IAAoB;QAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACrC,IAAI,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACjD,WAAW,GAAG,EAAE,SAAS,EAAE,WAAW,CAAC,SAAS,GAAG,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC;QAC/E,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC;IAC3E,CAAC;CACF"}
@@ -0,0 +1,25 @@
import { CodeAction } from 'vscode-languageserver-types';
import { ClientCapabilities, CodeActionParams } from 'vscode-languageserver-protocol';
import { TextDocument } from 'vscode-languageserver-textdocument';
import { LanguageSettings } from '../yamlLanguageService';
export declare class YamlCodeActions {
private readonly clientCapabilities;
private indentation;
private lineWidth;
constructor(clientCapabilities: ClientCapabilities);
configure(settings: LanguageSettings, printWidth: number): void;
getCodeAction(document: TextDocument, params: CodeActionParams): CodeAction[] | undefined;
private getJumpToSchemaActions;
private getTabToSpaceConverting;
private getUnusedAnchorsDelete;
private getConvertToBooleanActions;
private getConvertToBlockStyleActions;
private getConvertStringToBlockStyleActions;
private getKeyOrderActions;
/**
* Check if diagnostic contains info for quick fix
* Supports Enum/Const/Property mismatch
*/
private getPossibleQuickFixValues;
private getQuickFixForPropertyOrValueMismatch;
}
@@ -0,0 +1,342 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as l10n from '@vscode/l10n';
import * as path from 'path';
import { ErrorCode } from 'vscode-json-languageservice';
import { CodeAction, CodeActionKind, Command, Position, Range, TextEdit, } from 'vscode-languageserver-types';
import { CST, isMap, isSeq, isScalar, visit } from 'yaml';
import { YamlCommands } from '../../commands';
import { TextBuffer } from '../utils/textBuffer';
import { toYamlStringScalar } from '../utils/yamlScalar';
import { YAML_SOURCE } from '../parser/schemaValidation/baseValidator';
import { getFirstNonWhitespaceCharacterAfterOffset } from '../utils/strings';
import { matchOffsetToDocument } from '../utils/arrUtils';
import { yamlDocumentsCache } from '../parser/yaml-documents';
import { BlockStringRewriter } from '../utils/block-string-rewriter';
import { FlowStyleRewriter } from '../utils/flow-style-rewriter';
export class YamlCodeActions {
constructor(clientCapabilities) {
this.clientCapabilities = clientCapabilities;
this.indentation = ' ';
this.lineWidth = 80;
}
configure(settings, printWidth) {
this.indentation = settings.indentation;
this.lineWidth = printWidth;
}
getCodeAction(document, params) {
if (!params.context.diagnostics) {
return;
}
const result = [];
result.push(...this.getConvertToBooleanActions(params.context.diagnostics, document));
result.push(...this.getJumpToSchemaActions(params.context.diagnostics));
result.push(...this.getTabToSpaceConverting(params.context.diagnostics, document));
result.push(...this.getUnusedAnchorsDelete(params.context.diagnostics, document));
result.push(...this.getConvertToBlockStyleActions(params.context.diagnostics, document));
result.push(...this.getConvertStringToBlockStyleActions(params.range, document));
result.push(...this.getKeyOrderActions(params.context.diagnostics, document));
result.push(...this.getQuickFixForPropertyOrValueMismatch(params.context.diagnostics, document));
return result;
}
getJumpToSchemaActions(diagnostics) {
const isOpenTextDocumentEnabled = this.clientCapabilities?.window?.showDocument?.support ?? false;
if (!isOpenTextDocumentEnabled) {
return [];
}
const schemaUriToDiagnostic = new Map();
for (const diagnostic of diagnostics) {
const schemaUri = diagnostic.data?.schemaUri || [];
for (const schemaUriStr of schemaUri) {
if (schemaUriStr) {
if (!schemaUriToDiagnostic.has(schemaUriStr)) {
schemaUriToDiagnostic.set(schemaUriStr, []);
}
schemaUriToDiagnostic.get(schemaUriStr).push(diagnostic);
}
}
}
const result = [];
for (const schemaUri of schemaUriToDiagnostic.keys()) {
const action = CodeAction.create(l10n.t('Jump to schema location ({0})', path.basename(schemaUri)), Command.create('JumpToSchema', YamlCommands.JUMP_TO_SCHEMA, schemaUri));
action.diagnostics = schemaUriToDiagnostic.get(schemaUri);
result.push(action);
}
return result;
}
getTabToSpaceConverting(diagnostics, document) {
const result = [];
const textBuff = new TextBuffer(document);
const processedLine = [];
for (const diag of diagnostics) {
if (diag.message === 'Tabs are not allowed as indentation') {
if (processedLine.includes(diag.range.start.line)) {
continue;
}
const lineContent = textBuff.getLineContent(diag.range.start.line);
let replacedTabs = 0;
let newText = '';
for (let i = diag.range.start.character; i <= diag.range.end.character; i++) {
const char = lineContent.charAt(i);
if (char !== '\t') {
break;
}
replacedTabs++;
newText += this.indentation;
}
processedLine.push(diag.range.start.line);
let resultRange = diag.range;
if (replacedTabs !== diag.range.end.character - diag.range.start.character) {
resultRange = Range.create(diag.range.start, Position.create(diag.range.end.line, diag.range.start.character + replacedTabs));
}
result.push(CodeAction.create(l10n.t('Convert Tab to Spaces'), createWorkspaceEdit(document.uri, [TextEdit.replace(resultRange, newText)]), CodeActionKind.QuickFix));
}
}
if (result.length !== 0) {
const replaceEdits = [];
for (let i = 0; i <= textBuff.getLineCount(); i++) {
const lineContent = textBuff.getLineContent(i);
let replacedTabs = 0;
let newText = '';
for (let j = 0; j < lineContent.length; j++) {
const char = lineContent.charAt(j);
if (char !== ' ' && char !== '\t') {
if (replacedTabs !== 0) {
replaceEdits.push(TextEdit.replace(Range.create(i, j - replacedTabs, i, j), newText));
replacedTabs = 0;
newText = '';
}
break;
}
if (char === ' ' && replacedTabs !== 0) {
replaceEdits.push(TextEdit.replace(Range.create(i, j - replacedTabs, i, j), newText));
replacedTabs = 0;
newText = '';
continue;
}
if (char === '\t') {
newText += this.indentation;
replacedTabs++;
}
}
// line contains only tabs
if (replacedTabs !== 0) {
replaceEdits.push(TextEdit.replace(Range.create(i, 0, i, textBuff.getLineLength(i)), newText));
}
}
if (replaceEdits.length > 0) {
result.push(CodeAction.create(l10n.t('Convert all Tabs to Spaces'), createWorkspaceEdit(document.uri, replaceEdits), CodeActionKind.QuickFix));
}
}
return result;
}
getUnusedAnchorsDelete(diagnostics, document) {
const result = [];
const buffer = new TextBuffer(document);
for (const diag of diagnostics) {
if (diag.message.startsWith('Unused anchor') && diag.source === YAML_SOURCE) {
const range = Range.create(diag.range.start, diag.range.end);
const actual = buffer.getText(range);
const lineContent = buffer.getLineContent(range.end.line);
const lastWhitespaceChar = getFirstNonWhitespaceCharacterAfterOffset(lineContent, range.end.character);
range.end.character = lastWhitespaceChar;
const action = CodeAction.create(l10n.t('Delete unused anchor: {0}', actual), createWorkspaceEdit(document.uri, [TextEdit.del(range)]), CodeActionKind.QuickFix);
action.diagnostics = [diag];
result.push(action);
}
}
return result;
}
getConvertToBooleanActions(diagnostics, document) {
const results = [];
for (const diagnostic of diagnostics) {
if (diagnostic.message === 'Incorrect type. Expected "boolean".') {
const value = document.getText(diagnostic.range).toLocaleLowerCase();
if (value === '"true"' || value === '"false"' || value === "'true'" || value === "'false'") {
const newValue = value.includes('true') ? 'true' : 'false';
results.push(CodeAction.create(l10n.t('Convert to boolean'), createWorkspaceEdit(document.uri, [TextEdit.replace(diagnostic.range, newValue)]), CodeActionKind.QuickFix));
}
}
}
return results;
}
getConvertToBlockStyleActions(diagnostics, document) {
const results = [];
for (const diagnostic of diagnostics) {
if (diagnostic.code === 'flowMap' || diagnostic.code === 'flowSeq') {
const node = getNodeForDiagnostic(document, diagnostic);
if (isMap(node.internalNode) || isSeq(node.internalNode)) {
const blockTypeDescription = isMap(node.internalNode) ? 'map' : 'sequence';
const rewriter = new FlowStyleRewriter(this.indentation);
results.push(CodeAction.create(l10n.t('Convert to block style {0}', blockTypeDescription), createWorkspaceEdit(document.uri, [TextEdit.replace(diagnostic.range, rewriter.write(node))]), CodeActionKind.QuickFix));
}
}
}
return results;
}
getConvertStringToBlockStyleActions(range, document) {
const yamlDocument = yamlDocumentsCache.getYamlDocument(document);
const startOffset = range ? document.offsetAt(range.start) : 0;
const endOffset = range ? document.offsetAt(range.end) : Infinity;
const results = [];
for (const singleYamlDocument of yamlDocument.documents) {
const matchingNodes = [];
visit(singleYamlDocument.internalDocument, (key, node) => {
if (isScalar(node)) {
if ((startOffset <= node.range[0] && node.range[2] <= endOffset) ||
(node.range[0] <= startOffset && endOffset <= node.range[2])) {
if (node.type === 'QUOTE_DOUBLE' || node.type === 'QUOTE_SINGLE') {
if (typeof node.value === 'string' && (node.value.indexOf('\n') >= 0 || node.value.length > this.lineWidth)) {
matchingNodes.push(node);
}
}
}
}
});
for (const node of matchingNodes) {
const range = Range.create(document.positionAt(node.range[0]), document.positionAt(node.range[1]));
const rewriter = new BlockStringRewriter(this.indentation, this.lineWidth);
const foldedBlockScalar = rewriter.writeFoldedBlockScalar(node);
if (foldedBlockScalar !== null) {
results.push(CodeAction.create(l10n.t('Convert string to folded block string'), createWorkspaceEdit(document.uri, [TextEdit.replace(range, foldedBlockScalar)]), CodeActionKind.Refactor));
}
const literalBlockScalar = rewriter.writeLiteralBlockScalar(node);
if (literalBlockScalar !== null) {
results.push(CodeAction.create(l10n.t('Convert string to literal block string'), createWorkspaceEdit(document.uri, [TextEdit.replace(range, literalBlockScalar)]), CodeActionKind.Refactor));
}
}
}
return results;
}
getKeyOrderActions(diagnostics, document) {
const results = [];
for (const diagnostic of diagnostics) {
if (diagnostic?.code === 'mapKeyOrder') {
let node = getNodeForDiagnostic(document, diagnostic);
while (node && node.type !== 'object') {
node = node.parent;
}
if (node && isMap(node.internalNode)) {
const sorted = structuredClone(node.internalNode);
const _getTrailingTokens = (value) => {
if (!value)
return;
if (CST.isScalar(value)) {
if (value.type === 'block-scalar') {
value.props ?? (value.props = []);
return value.props;
}
value.end ?? (value.end = []);
return value.end;
}
if (value.type === 'flow-collection') {
value.end ?? (value.end = []);
return value.end;
}
if (value.type === 'block-map') {
const lastItem = value.items[value.items.length - 1];
return lastItem ? _getTrailingTokens(lastItem.value) : undefined;
}
return;
};
if ((sorted.srcToken.type === 'block-map' || sorted.srcToken.type === 'flow-collection') &&
(node.internalNode.srcToken.type === 'block-map' || node.internalNode.srcToken.type === 'flow-collection')) {
sorted.srcToken.items.sort((a, b) => {
if (a.key && b.key && CST.isScalar(a.key) && CST.isScalar(b.key)) {
return a.key.source.localeCompare(b.key.source);
}
if (!a.key && b.key) {
return -1;
}
if (a.key && !b.key) {
return 1;
}
if (!a.key && !b.key) {
return 0;
}
});
for (let i = 0; i < sorted.srcToken.items.length; i++) {
const item = sorted.srcToken.items[i];
const uItem = node.internalNode.srcToken.items[i];
item.start = uItem.start;
// strip leading blank lines so reordered entries stay one-per-line
while (item.start?.[0]?.type === 'newline')
item.start.shift();
const itemTokens = _getTrailingTokens(item.value);
const itemNewLineIndex = itemTokens?.findIndex((p) => p.type === 'newline') ?? -1;
const uNewLineToken = _getTrailingTokens(uItem.value)?.find((p) => p.type === 'newline' && p.offset < node.offset + node.length) ??
null;
if (uNewLineToken && itemNewLineIndex < 0 && itemTokens) {
itemTokens.push({ type: 'newline', indent: 0, offset: item.value.offset, source: '\n' });
}
if (!uNewLineToken && itemNewLineIndex > -1 && itemTokens) {
itemTokens.splice(itemNewLineIndex, 1);
}
}
}
const replaceRange = Range.create(document.positionAt(node.offset), document.positionAt(node.offset + node.length));
results.push(CodeAction.create(l10n.t('Fix key order for this map'), createWorkspaceEdit(document.uri, [TextEdit.replace(replaceRange, CST.stringify(sorted.srcToken))]), CodeActionKind.QuickFix));
}
}
}
return results;
}
/**
* Check if diagnostic contains info for quick fix
* Supports Enum/Const/Property mismatch
*/
getPossibleQuickFixValues(diagnostic) {
if (typeof diagnostic.data !== 'object') {
return;
}
if (diagnostic.code === ErrorCode.EnumValueMismatch &&
'values' in diagnostic.data &&
Array.isArray(diagnostic.data.values)) {
return diagnostic.data.values;
}
else if (diagnostic.code === ErrorCode.PropertyExpected &&
'properties' in diagnostic.data &&
Array.isArray(diagnostic.data.properties)) {
return diagnostic.data.properties;
}
}
getQuickFixForPropertyOrValueMismatch(diagnostics, document) {
const results = [];
for (const diagnostic of diagnostics) {
const values = this.getPossibleQuickFixValues(diagnostic);
if (!values?.length) {
continue;
}
for (const value of values) {
const scalar = typeof value === 'string' ? toYamlStringScalar(value) : String(value);
results.push(CodeAction.create(scalar, createWorkspaceEdit(document.uri, [TextEdit.replace(diagnostic.range, scalar)]), CodeActionKind.QuickFix));
}
}
return results;
}
}
function getNodeForDiagnostic(document, diagnostic) {
const yamlDocuments = yamlDocumentsCache.getYamlDocument(document);
const startOffset = document.offsetAt(diagnostic.range.start);
const endOffset = document.offsetAt(diagnostic.range.end);
const yamlDoc = matchOffsetToDocument(startOffset, yamlDocuments);
let node = yamlDoc.getNodeFromOffset(startOffset);
if (node && startOffset < endOffset && node.offset + node.length === startOffset) {
const nodeInsideRange = yamlDoc.getNodeFromOffset(startOffset + 1);
if (nodeInsideRange) {
node = nodeInsideRange;
}
}
return node;
}
function createWorkspaceEdit(uri, edits) {
const changes = {};
changes[uri] = edits;
const edit = {
changes,
};
return edit;
}
//# sourceMappingURL=yamlCodeActions.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
import { TextDocument } from 'vscode-languageserver-textdocument';
import { CodeLens } from 'vscode-languageserver-types';
import { YAMLSchemaService } from './yamlSchemaService';
import { Telemetry } from '../telemetry';
export declare class YamlCodeLens {
private schemaService;
private readonly telemetry?;
constructor(schemaService: YAMLSchemaService, telemetry?: Telemetry);
getCodeLens(document: TextDocument): Promise<CodeLens[]>;
resolveCodeLens(param: CodeLens): PromiseLike<CodeLens> | CodeLens;
}
@@ -0,0 +1,46 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CodeLens, Range } from 'vscode-languageserver-types';
import { YamlCommands } from '../../commands';
import { yamlDocumentsCache } from '../parser/yaml-documents';
import { getSchemaUrls } from '../utils/schemaUrls';
import { getSchemaTitle } from '../utils/schemaUtils';
export class YamlCodeLens {
constructor(schemaService, telemetry) {
this.schemaService = schemaService;
this.telemetry = telemetry;
}
async getCodeLens(document) {
const result = [];
try {
const yamlDocument = yamlDocumentsCache.getYamlDocument(document);
let schemaUrls = new Map();
for (const currentYAMLDoc of yamlDocument.documents) {
const schema = await this.schemaService.getSchemaForResource(document.uri, currentYAMLDoc);
if (schema?.schema) {
// merge schemas from all docs to avoid duplicates
schemaUrls = new Map([...getSchemaUrls(schema?.schema), ...schemaUrls]);
}
}
for (const urlToSchema of schemaUrls) {
const lens = CodeLens.create(Range.create(0, 0, 0, 0));
lens.command = {
title: getSchemaTitle(urlToSchema[1], urlToSchema[0]),
command: YamlCommands.JUMP_TO_SCHEMA,
arguments: [urlToSchema[0]],
};
result.push(lens);
}
}
catch (err) {
this.telemetry?.sendError('yaml.codeLens.error', err);
}
return result;
}
resolveCodeLens(param) {
return param;
}
}
//# sourceMappingURL=yamlCodeLens.js.map
@@ -0,0 +1 @@
{"version":3,"file":"yamlCodeLens.js","sourceRoot":"","sources":["../../../../src/languageservice/services/yamlCodeLens.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAGhG,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAI9D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,OAAO,YAAY;IACvB,YACU,aAAgC,EACvB,SAAqB;QAD9B,kBAAa,GAAb,aAAa,CAAmB;QACvB,cAAS,GAAT,SAAS,CAAY;IACrC,CAAC;IAEJ,KAAK,CAAC,WAAW,CAAC,QAAsB;QACtC,MAAM,MAAM,GAAG,EAAE,CAAC;QAClB,IAAI;YACF,MAAM,YAAY,GAAG,kBAAkB,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;YAClE,IAAI,UAAU,GAAG,IAAI,GAAG,EAAsB,CAAC;YAC/C,KAAK,MAAM,cAAc,IAAI,YAAY,CAAC,SAAS,EAAE;gBACnD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,oBAAoB,CAAC,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;gBAC3F,IAAI,MAAM,EAAE,MAAM,EAAE;oBAClB,kDAAkD;oBAClD,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC;iBACzE;aACF;YACD,KAAK,MAAM,WAAW,IAAI,UAAU,EAAE;gBACpC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACvD,IAAI,CAAC,OAAO,GAAG;oBACb,KAAK,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;oBACrD,OAAO,EAAE,YAAY,CAAC,cAAc;oBACpC,SAAS,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;iBAC5B,CAAC;gBACF,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aACnB;SACF;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;SACvD;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,eAAe,CAAC,KAAe;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
@@ -0,0 +1,3 @@
import { Connection } from 'vscode-languageserver';
import { CommandExecutor } from '../../languageserver/commandExecutor';
export declare function registerCommands(commandExecutor: CommandExecutor, connection: Connection): void;
@@ -0,0 +1,46 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { YamlCommands } from '../../commands';
import { URI } from 'vscode-uri';
export function registerCommands(commandExecutor, connection) {
commandExecutor.registerCommand(YamlCommands.JUMP_TO_SCHEMA, async (uri) => {
if (!uri) {
return;
}
const wsFolders = await connection.workspace.getWorkspaceFolders();
if (uri.indexOf('://') < 0 && !uri.startsWith('/')) {
if (wsFolders.length === 1) {
const wsUri = URI.parse(wsFolders[0].uri);
uri = wsUri.with({ path: wsUri.path + uri }).toString();
}
}
else if (uri.startsWith('file://') && wsFolders.length === 1 && URI.parse(wsFolders[0].uri).scheme != 'file') {
const wsUri = URI.parse(wsFolders[0].uri);
const pathFromUri = URI.parse(uri).path;
uri = wsUri.with({ path: pathFromUri }).toString();
}
else if (!uri.startsWith('file') && !/^[a-z]:[\\/]/i.test(uri)) {
// if uri points to local file of its a windows path
const origUri = URI.parse(uri);
const customUri = URI.from({
scheme: 'json-schema',
authority: origUri.authority,
path: origUri.path.endsWith('.json') ? origUri.path : origUri.path + '.json',
fragment: uri,
});
uri = customUri.toString();
}
// test if uri is windows path, ie starts with 'c:\' and convert to URI
if (/^[a-z]:[\\/]/i.test(uri)) {
const winUri = URI.file(uri);
uri = winUri.toString();
}
const result = await connection.window.showDocument({ uri: uri, external: false, takeFocus: true });
if (!result) {
connection.window.showErrorMessage(`Cannot open ${uri}`);
}
});
}
//# sourceMappingURL=yamlCommands.js.map
@@ -0,0 +1 @@
{"version":3,"file":"yamlCommands.js","sourceRoot":"","sources":["../../../../src/languageservice/services/yamlCommands.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAGhG,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEjC,MAAM,UAAU,gBAAgB,CAAC,eAAgC,EAAE,UAAsB;IACvF,eAAe,CAAC,eAAe,CAAC,YAAY,CAAC,cAAc,EAAE,KAAK,EAAE,GAAW,EAAE,EAAE;QACjF,IAAI,CAAC,GAAG,EAAE;YACR,OAAO;SACR;QACD,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,mBAAmB,EAAE,CAAC;QAEnE,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;YAClD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE;gBAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBAC1C,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,GAAG,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;aACzD;SACF;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,MAAM,EAAE;YAC9G,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAC1C,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACxC,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;SACpD;aAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAChE,oDAAoD;YACpD,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/B,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC;gBACzB,MAAM,EAAE,aAAa;gBACrB,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,GAAG,OAAO;gBAC5E,QAAQ,EAAE,GAAG;aACd,CAAC,CAAC;YACH,GAAG,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC;SAC5B;QAED,uEAAuE;QACvE,IAAI,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAC7B,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC7B,GAAG,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;SACzB;QAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpG,IAAI,CAAC,MAAM,EAAE;YACX,UAAU,CAAC,MAAM,CAAC,gBAAgB,CAAC,eAAe,GAAG,EAAE,CAAC,CAAC;SAC1D;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,77 @@
import { TextDocument } from 'vscode-languageserver-textdocument';
import { ClientCapabilities } from 'vscode-languageserver';
import { CompletionItem as CompletionItemBase, CompletionList, Position } from 'vscode-languageserver-types';
import { Telemetry } from '../telemetry';
import { YamlDocuments } from '../parser/yaml-documents';
import { LanguageSettings } from '../yamlLanguageService';
import { YAMLSchemaService } from './yamlSchemaService';
import { JSONSchema } from '../jsonSchema';
import { SettingsState } from '../../yamlSettings';
interface ParentCompletionItemOptions {
schema: JSONSchema;
indent?: string;
insertTexts?: string[];
}
interface CompletionItem extends CompletionItemBase {
parent?: ParentCompletionItemOptions;
}
export declare class YamlCompletion {
private schemaService;
private clientCapabilities;
private yamlDocument;
private readonly telemetry?;
private customTags;
private completionEnabled;
private configuredIndentation;
private yamlVersion;
private isSingleQuote;
private indentation;
private arrayPrefixIndentation;
private supportsMarkdown;
private disableDefaultProperties;
private parentSkeletonSelectedFirst;
constructor(schemaService: YAMLSchemaService, clientCapabilities: ClientCapabilities, yamlDocument: YamlDocuments, telemetry?: Telemetry);
configure(languageSettings: LanguageSettings, yamlSettings?: SettingsState): void;
doComplete(document: TextDocument, position: Position, isKubernetes?: boolean, doComplete?: boolean): Promise<CompletionList>;
updateCompletionText(completionItem: CompletionItem, text: string): void;
mergeSimpleInsertTexts(label: string, existingText: string, addingText: string, oneOfSchema: boolean): string | undefined;
getValuesFromInsertText(insertText: string): string[];
private finalizeParentCompletion;
private createTempObjNode;
private addPropertyCompletions;
private getValueCompletions;
private addArrayItemValueCompletion;
private getInsertTextForProperty;
private getInsertTextForObject;
private getInsertTextForArray;
private getInsertTextForGuessedValue;
private getInsertTextForPlainText;
private getInsertTextForValue;
private getInsertTemplateForValue;
private addSchemaValueCompletions;
private collectTypes;
private addDefaultValueCompletions;
private addEnumValueCompletions;
private getLabelForValue;
private collectDefaultSnippets;
private getInsertTextForSnippetValue;
private addBooleanValueCompletion;
private addNullValueCompletion;
private getLabelForSnippetValue;
private getCustomTagValueCompletions;
private addCustomTagValueCompletion;
private getDocumentationWithMarkdownText;
private getSuggestionKind;
private getCurrentWord;
private fromMarkup;
private doesSupportMarkdown;
private findItemAtOffset;
private getPropertyNamesCandidates;
getQuote(): string;
/**
* simplify `{$1:value}` to `value`
*/
evaluateTab1Symbol(value: string): string;
isParentCompletionItem(item: CompletionItemBase): item is CompletionItem;
}
export {};
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
import { DefinitionParams } from 'vscode-languageserver-protocol';
import { TextDocument } from 'vscode-languageserver-textdocument';
import { DefinitionLink } from 'vscode-languageserver-types';
import { Telemetry } from '../telemetry';
export declare class YamlDefinition {
private readonly telemetry?;
constructor(telemetry?: Telemetry);
getDefinition(document: TextDocument, params: DefinitionParams): DefinitionLink[] | undefined;
}
@@ -0,0 +1,37 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { LocationLink, Range } from 'vscode-languageserver-types';
import { isAlias } from 'yaml';
import { yamlDocumentsCache } from '../parser/yaml-documents';
import { matchOffsetToDocument } from '../utils/arrUtils';
import { TextBuffer } from '../utils/textBuffer';
export class YamlDefinition {
constructor(telemetry) {
this.telemetry = telemetry;
}
getDefinition(document, params) {
try {
const yamlDocument = yamlDocumentsCache.getYamlDocument(document);
const offset = document.offsetAt(params.position);
const currentDoc = matchOffsetToDocument(offset, yamlDocument);
if (currentDoc) {
const [node] = currentDoc.getNodeFromPosition(offset, new TextBuffer(document));
if (node && isAlias(node)) {
const defNode = node.resolve(currentDoc.internalDocument);
if (defNode && defNode.range) {
const targetRange = Range.create(document.positionAt(defNode.range[0]), document.positionAt(defNode.range[2]));
const selectionRange = Range.create(document.positionAt(defNode.range[0]), document.positionAt(defNode.range[1]));
return [LocationLink.create(document.uri, targetRange, selectionRange)];
}
}
}
}
catch (err) {
this.telemetry?.sendError('yaml.definition.error', err);
}
return undefined;
}
}
//# sourceMappingURL=yamlDefinition.js.map
@@ -0,0 +1 @@
{"version":3,"file":"yamlDefinition.js","sourceRoot":"","sources":["../../../../src/languageservice/services/yamlDefinition.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAIhG,OAAO,EAAkB,YAAY,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAClF,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,OAAO,cAAc;IACzB,YAA6B,SAAqB;QAArB,cAAS,GAAT,SAAS,CAAY;IAAG,CAAC;IAEtD,aAAa,CAAC,QAAsB,EAAE,MAAwB;QAC5D,IAAI;YACF,MAAM,YAAY,GAAG,kBAAkB,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;YAClE,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAClD,MAAM,UAAU,GAAG,qBAAqB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YAC/D,IAAI,UAAU,EAAE;gBACd,MAAM,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,mBAAmB,CAAC,MAAM,EAAE,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAChF,IAAI,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE;oBACzB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;oBAC1D,IAAI,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE;wBAC5B,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBAC/G,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBAClH,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC;qBACzE;iBACF;aACF;SACF;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;SACzD;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1,4 @@
import { FoldingRange } from 'vscode-languageserver-types';
import { FoldingRangesContext } from '../yamlTypes';
import { TextDocument } from 'vscode-languageserver-textdocument';
export declare function getFoldingRanges(document: TextDocument, context: FoldingRangesContext): FoldingRange[] | undefined;
@@ -0,0 +1,62 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { FoldingRange, Range } from 'vscode-languageserver-types';
import { yamlDocumentsCache } from '../parser/yaml-documents';
export function getFoldingRanges(document, context) {
if (!document) {
return;
}
const result = [];
const doc = yamlDocumentsCache.getYamlDocument(document);
for (const ymlDoc of doc.documents) {
if (doc.documents.length > 1) {
result.push(createNormalizedFolding(document, ymlDoc.root));
}
ymlDoc.visit((node) => {
if (node.type === 'object' && node.parent?.type === 'array') {
result.push(createNormalizedFolding(document, node));
}
if (node.type === 'property' && node.valueNode) {
switch (node.valueNode.type) {
case 'array':
case 'object':
result.push(createNormalizedFolding(document, node));
break;
case 'string': {
// check if it is a multi-line string
const nodePosn = document.positionAt(node.offset);
const valuePosn = document.positionAt(node.valueNode.offset + node.valueNode.length);
if (nodePosn.line !== valuePosn.line) {
result.push(createNormalizedFolding(document, node));
}
break;
}
default:
return true;
}
}
return true;
});
}
const rangeLimit = context && context.rangeLimit;
if (typeof rangeLimit !== 'number' || result.length <= rangeLimit) {
return result;
}
if (context && context.onRangeLimitExceeded) {
context.onRangeLimitExceeded(document.uri);
}
return result.slice(0, context.rangeLimit);
}
function createNormalizedFolding(document, node) {
const startPos = document.positionAt(node.offset);
let endPos = document.positionAt(node.offset + node.length);
const textFragment = document.getText(Range.create(startPos, endPos));
const newLength = textFragment.length - textFragment.trimRight().length;
if (newLength > 0) {
endPos = document.positionAt(node.offset + node.length - newLength);
}
return FoldingRange.create(startPos.line, endPos.line, startPos.character, endPos.character);
}
//# sourceMappingURL=yamlFolding.js.map
@@ -0,0 +1 @@
{"version":3,"file":"yamlFolding.js","sourceRoot":"","sources":["../../../../src/languageservice/services/yamlFolding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
import { TextEdit, FormattingOptions } from 'vscode-languageserver-types';
import { CustomFormatterOptions, LanguageSettings } from '../yamlLanguageService';
import { TextDocument } from 'vscode-languageserver-textdocument';
export declare class YAMLFormatter {
private formatterEnabled;
configure(shouldFormat: LanguageSettings): void;
format(document: TextDocument, options?: Partial<FormattingOptions> & CustomFormatterOptions): Promise<TextEdit[]>;
}
@@ -0,0 +1,46 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Copyright (c) Adam Voss. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Range, Position, TextEdit } from 'vscode-languageserver-types';
import * as yamlPlugin from 'prettier/plugins/yaml';
import * as estreePlugin from 'prettier/plugins/estree';
import { format } from 'prettier/standalone';
export class YAMLFormatter {
constructor() {
this.formatterEnabled = true;
}
configure(shouldFormat) {
if (shouldFormat) {
this.formatterEnabled = shouldFormat.format;
}
}
async format(document, options = {}) {
if (!this.formatterEnabled) {
return [];
}
try {
const text = document.getText();
const prettierOptions = {
parser: 'yaml',
plugins: [yamlPlugin, estreePlugin],
// --- FormattingOptions ---
tabWidth: options.tabWidth || options.tabSize,
// --- CustomFormatterOptions ---
singleQuote: options.singleQuote,
bracketSpacing: options.bracketSpacing,
// 'preserve' is the default for Options.proseWrap. See also server.ts
proseWrap: 'always' === options.proseWrap ? 'always' : 'never' === options.proseWrap ? 'never' : 'preserve',
printWidth: options.printWidth,
trailingComma: options.trailingComma === false ? 'none' : 'all',
};
const formatted = await format(text, prettierOptions);
return [TextEdit.replace(Range.create(Position.create(0, 0), document.positionAt(text.length)), formatted)];
}
catch (error) {
return [];
}
}
}
//# sourceMappingURL=yamlFormatter.js.map
@@ -0,0 +1 @@
{"version":3,"file":"yamlFormatter.js","sourceRoot":"","sources":["../../../../src/languageservice/services/yamlFormatter.ts"],"names":[],"mappings":"AAAA;;;;gGAIgG;AAEhG,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAqB,MAAM,6BAA6B,CAAC;AAG3F,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,YAAY,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAG7C,MAAM,OAAO,aAAa;IAA1B;QACU,qBAAgB,GAAG,IAAI,CAAC;IA0ClC,CAAC;IAxCQ,SAAS,CAAC,YAA8B;QAC7C,IAAI,YAAY,EAAE;YAChB,IAAI,CAAC,gBAAgB,GAAG,YAAY,CAAC,MAAM,CAAC;SAC7C;IACH,CAAC;IAEM,KAAK,CAAC,MAAM,CACjB,QAAsB,EACtB,UAA+D,EAAE;QAEjE,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;YAC1B,OAAO,EAAE,CAAC;SACX;QAED,IAAI;YACF,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;YAEhC,MAAM,eAAe,GAAY;gBAC/B,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,CAAC,UAAU,EAAE,YAAY,CAAC;gBAEnC,4BAA4B;gBAC5B,QAAQ,EAAG,OAAO,CAAC,QAAmB,IAAI,OAAO,CAAC,OAAO;gBAEzD,iCAAiC;gBACjC,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,cAAc,EAAE,OAAO,CAAC,cAAc;gBACtC,sEAAsE;gBACtE,SAAS,EAAE,QAAQ,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU;gBAC3G,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,aAAa,EAAE,OAAO,CAAC,aAAa,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK;aAChE,CAAC;YAEF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;YAEtD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;SAC7G;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,EAAE,CAAC;SACX;IACH,CAAC;CACF"}
@@ -0,0 +1,47 @@
import { TextDocument } from 'vscode-languageserver-textdocument';
import { Hover, Position } from 'vscode-languageserver-types';
import { Telemetry } from '../telemetry';
import { LanguageSettings } from '../yamlLanguageService';
import { YAMLSchemaService } from './yamlSchemaService';
export declare class YAMLHover {
private readonly telemetry?;
private shouldHover;
private shouldHoverAnchor;
private indentation;
private schemaService;
constructor(schemaService: YAMLSchemaService, telemetry?: Telemetry);
configure(languageSettings: LanguageSettings): void;
doHover(document: TextDocument, position: Position, isKubernetes?: boolean): Promise<Hover | null>;
private getHover;
/**
* Resolves merge keys (<<) and anchors recursively in an object node
* @param node The object AST node to resolve
* @param doc The YAML document for resolving anchors
* @param currentRecursionLevel Current recursion level (default: 0)
* @returns A plain JavaScript object with all merges resolved
*/
private resolveMergeKeys;
/**
* Resolves a merge value (which might be an alias) and recursively resolves its merge keys
* @param node The AST node that might be an alias or object
* @param doc The YAML document for resolving anchors
* @param currentRecursionLevel Current recursion level
* @returns The resolved value
*/
private resolveMergeValue;
/**
* Converts an AST node to a plain JavaScript value
* @param node The AST node to convert
* @param doc The YAML document for resolving anchors
* @param currentRecursionLevel Current recursion level
* @returns The converted value
*/
private astNodeToValue;
/**
* Converts a YAML Node to a plain JavaScript value
* @param node The YAML node to convert
* @returns The converted value
*/
private nodeToValue;
private toMarkdown;
}
@@ -0,0 +1,366 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as l10n from '@vscode/l10n';
import * as path from 'path';
import { MarkupKind, Range } from 'vscode-languageserver-types';
import { URI } from 'vscode-uri';
import { isAlias, isMap, isSeq, stringify as stringifyYAML } from 'yaml';
import { setKubernetesParserOption } from '../parser/isKubernetes';
import { getNodeValue } from '../parser/astNodeUtils';
import { yamlDocumentsCache } from '../parser/yaml-documents';
import { matchOffsetToDocument } from '../utils/arrUtils';
import { toYamlStringScalar } from '../utils/yamlScalar';
export class YAMLHover {
constructor(schemaService, telemetry) {
this.telemetry = telemetry;
this.shouldHover = true;
this.schemaService = schemaService;
}
configure(languageSettings) {
if (languageSettings) {
this.shouldHover = languageSettings.hover;
this.shouldHoverAnchor = languageSettings.hoverAnchor;
this.indentation = languageSettings.indentation;
}
}
doHover(document, position, isKubernetes = false) {
try {
if (!this.shouldHover || !document) {
return Promise.resolve(undefined);
}
const doc = yamlDocumentsCache.getYamlDocument(document);
const offset = document.offsetAt(position);
const currentDoc = matchOffsetToDocument(offset, doc);
if (currentDoc === null) {
return Promise.resolve(undefined);
}
setKubernetesParserOption(doc.documents, isKubernetes);
const currentDocIndex = doc.documents.indexOf(currentDoc);
currentDoc.currentDocIndex = currentDocIndex;
return this.getHover(document, position, currentDoc);
}
catch (error) {
this.telemetry?.sendError('yaml.hover.error', error);
}
}
// method copied from https://github.com/microsoft/vscode-json-languageservice/blob/2ea5ad3d2ffbbe40dea11cfe764a502becf113ce/src/services/jsonHover.ts#L23
getHover(document, position, doc) {
const offset = document.offsetAt(position);
let node = doc.getNodeFromOffset(offset);
if (!node ||
((node.type === 'object' || node.type === 'array') && offset > node.offset + 1 && offset < node.offset + node.length - 1)) {
return Promise.resolve(null);
}
const hoverRangeNode = node;
// use the property description when hovering over an object key
if (node.type === 'string') {
const parent = node.parent;
if (parent && parent.type === 'property' && parent.keyNode === node) {
node = parent.valueNode;
if (!node) {
return Promise.resolve(null);
}
}
}
const hoverRange = Range.create(document.positionAt(hoverRangeNode.offset), document.positionAt(hoverRangeNode.offset + hoverRangeNode.length));
const createHover = (contents) => {
const markupContent = {
kind: MarkupKind.Markdown,
value: contents,
};
const result = {
contents: markupContent,
range: hoverRange,
};
return result;
};
if (this.shouldHoverAnchor && node.type === 'property' && node.valueNode) {
if (node.valueNode.type === 'object') {
const resolved = this.resolveMergeKeys(node.valueNode, doc);
const contents = '```yaml\n' + stringifyYAML(resolved, null, 2) + '\n```';
return Promise.resolve(createHover(contents));
}
}
const removePipe = (value) => {
return value.replace(/\s\|\|\s*$/, '');
};
return this.schemaService.getSchemaForResource(document.uri, doc).then((schema) => {
if (schema && node && !schema.errors.length) {
const matchingSchemas = doc.getMatchingSchemas(schema.schema, node.offset);
let title = undefined;
let markdownDescription = undefined;
let markdownEnumDescriptions = [];
const markdownExamples = [];
const markdownEnums = [];
let enumIdx = undefined;
matchingSchemas.every((s) => {
if ((s.node === node || (node.type === 'property' && node.valueNode === s.node)) && !s.inverted && s.schema) {
title = title || s.schema.title || s.schema.closestTitle;
markdownDescription = markdownDescription || s.schema.markdownDescription || this.toMarkdown(s.schema.description);
if (s.schema.enum) {
enumIdx = s.schema.enum.indexOf(getNodeValue(node));
if (s.schema.markdownEnumDescriptions) {
markdownEnumDescriptions = s.schema.markdownEnumDescriptions;
}
else if (s.schema.enumDescriptions) {
markdownEnumDescriptions = s.schema.enumDescriptions.map(this.toMarkdown, this);
}
else {
markdownEnumDescriptions = [];
}
s.schema.enum.forEach((enumValue, idx) => {
var _a;
enumValue = typeof enumValue === 'string' ? toYamlStringScalar(enumValue, false) : JSON.stringify(enumValue);
//insert only if the value is not present yet (avoiding duplicates)
//but it also adds or keeps the description of the enum value
const foundIdx = markdownEnums.findIndex((me) => me.value === enumValue);
if (foundIdx < 0) {
markdownEnums.push({
value: enumValue,
description: markdownEnumDescriptions[idx],
});
}
else {
(_a = markdownEnums[foundIdx]).description || (_a.description = markdownEnumDescriptions[idx]);
}
});
}
if (s.schema.anyOf && isAllSchemasMatched(node, matchingSchemas, s.schema)) {
//if append title and description of all matched schemas on hover
title = '';
markdownDescription = s.schema.description ? s.schema.description + '\n' : '';
s.schema.anyOf.forEach((childSchema, index) => {
title += childSchema.title || s.schema.closestTitle || '';
markdownDescription += childSchema.markdownDescription || this.toMarkdown(childSchema.description) || '';
if (index !== s.schema.anyOf.length - 1) {
title += ' || ';
markdownDescription += ' || ';
}
});
title = removePipe(title);
markdownDescription = removePipe(markdownDescription);
}
if (s.schema.examples) {
s.schema.examples.forEach((example) => {
markdownExamples.push(stringifyYAML(example, null, 2));
});
}
}
return true;
});
let result = '';
if (title) {
result = '#### ' + this.toMarkdown(title);
}
if (markdownDescription) {
result = ensureLineBreak(result);
result += markdownDescription;
}
if (markdownEnums.length !== 0) {
result = ensureLineBreak(result);
result += l10n.t('Allowed Values:') + '\n\n';
if (enumIdx) {
markdownEnums.unshift(markdownEnums.splice(enumIdx, 1)[0]);
}
markdownEnums.forEach((me) => {
if (me.description) {
result += `* \`${toMarkdownCodeBlock(me.value)}\`: ${me.description}\n`;
}
else {
result += `* \`${toMarkdownCodeBlock(me.value)}\`\n`;
}
});
}
if (markdownExamples.length !== 0) {
markdownExamples.forEach((example) => {
result = ensureLineBreak(result);
result += l10n.t('Example:') + '\n\n';
result += `\`\`\`yaml\n${example}\`\`\`\n`;
});
}
if (result.length > 0 && schema.schema.url) {
result = ensureLineBreak(result);
result += l10n.t('Source: [{0}]({1})', getSchemaName(schema.schema), schema.schema.url);
}
return createHover(result);
}
return null;
});
}
/**
* Resolves merge keys (<<) and anchors recursively in an object node
* @param node The object AST node to resolve
* @param doc The YAML document for resolving anchors
* @param currentRecursionLevel Current recursion level (default: 0)
* @returns A plain JavaScript object with all merges resolved
*/
resolveMergeKeys(node, doc, currentRecursionLevel = 0) {
const result = {};
const unprocessedProperties = [...node.properties];
while (unprocessedProperties.length > 0) {
const propertyNode = unprocessedProperties.shift();
const key = propertyNode.keyNode.value;
if (key === '<<' && propertyNode.valueNode) {
// Handle merge key
const mergeValue = this.resolveMergeValue(propertyNode.valueNode, doc, currentRecursionLevel + 1);
if (mergeValue && typeof mergeValue === 'object' && !Array.isArray(mergeValue)) {
// Merge properties from the resolved value
const mergeKeys = Object.keys(mergeValue);
for (const mergeKey of mergeKeys) {
result[mergeKey] = mergeValue[mergeKey];
}
}
}
else {
// Regular property
result[key] = this.astNodeToValue(propertyNode.valueNode, doc, currentRecursionLevel);
}
}
return result;
}
/**
* Resolves a merge value (which might be an alias) and recursively resolves its merge keys
* @param node The AST node that might be an alias or object
* @param doc The YAML document for resolving anchors
* @param currentRecursionLevel Current recursion level
* @returns The resolved value
*/
resolveMergeValue(node, doc, currentRecursionLevel) {
const MAX_MERGE_RECURSION_LEVEL = 10;
// Check if we've exceeded max recursion level
if (currentRecursionLevel >= MAX_MERGE_RECURSION_LEVEL) {
return { '<<': node.parent.internalNode['value'] + ' (recursion limit reached)' };
}
// If it's an object node, resolve its merge keys
if (node.type === 'object') {
return this.resolveMergeKeys(node, doc, currentRecursionLevel);
}
// Otherwise, convert to value
return this.astNodeToValue(node, doc, currentRecursionLevel);
}
/**
* Converts an AST node to a plain JavaScript value
* @param node The AST node to convert
* @param doc The YAML document for resolving anchors
* @param currentRecursionLevel Current recursion level
* @returns The converted value
*/
astNodeToValue(node, doc, currentRecursionLevel) {
if (!node) {
return null;
}
switch (node.type) {
case 'object': {
return this.resolveMergeKeys(node, doc, currentRecursionLevel);
}
case 'array': {
return node.children.map((child) => this.astNodeToValue(child, doc, currentRecursionLevel));
}
case 'string':
case 'number':
case 'boolean':
case 'null': {
return node.value;
}
default: {
return this.nodeToValue(node.internalNode);
}
}
}
/**
* Converts a YAML Node to a plain JavaScript value
* @param node The YAML node to convert
* @returns The converted value
*/
nodeToValue(node) {
if (isAlias(node)) {
return node.source;
}
if (isMap(node)) {
const result = {};
for (const pair of node.items) {
if (pair.key && pair.value) {
const key = this.nodeToValue(pair.key);
const value = this.nodeToValue(pair.value);
if (typeof key === 'string') {
result[key] = value;
}
}
}
return result;
}
if (isSeq(node)) {
return node.items.map((item) => this.nodeToValue(item));
}
return node.value;
}
// copied from https://github.com/microsoft/vscode-json-languageservice/blob/2ea5ad3d2ffbbe40dea11cfe764a502becf113ce/src/services/jsonHover.ts#L112
toMarkdown(plain) {
if (plain) {
let escaped = plain.replace(/([^\n\r])(\r?\n)([^\n\r])/gm, '$1\n\n$3'); // single new lines to \n\n (Markdown paragraph)
escaped = escaped.replace(/[\\`*_{}[\]#+\-!]/g, '\\$&'); // escape some of the markdown syntax tokens http://daringfireball.net/projects/markdown/syntax#backslash to avoid unintended formatting
if (this.indentation !== undefined) {
// escape indentation whitespace to prevent it from being converted to markdown code blocks.
const indentationMatchRegex = new RegExp(` {${this.indentation.length}}`, 'g');
escaped = escaped.replace(indentationMatchRegex, '&emsp;');
}
return escaped;
}
return undefined;
}
}
function ensureLineBreak(content) {
if (content.length === 0) {
return content;
}
if (!content.endsWith('\n')) {
content += '\n';
}
return content + '\n';
}
function getSchemaName(schema) {
let result = 'JSON Schema';
const urlString = schema.url;
if (urlString) {
const url = URI.parse(urlString);
result = path.basename(url.fsPath);
}
else if (schema.title) {
result = schema.title;
}
return result;
}
// copied from https://github.com/microsoft/vscode-json-languageservice/blob/2ea5ad3d2ffbbe40dea11cfe764a502becf113ce/src/services/jsonHover.ts#L122
function toMarkdownCodeBlock(content) {
// see https://daringfireball.net/projects/markdown/syntax#precode
if (content.indexOf('`') !== -1) {
return '`` ' + content + ' ``';
}
return content;
}
/**
* check all the schemas which is inside anyOf presented or not in matching schema.
* @param node node
* @param matchingSchemas all matching schema
* @param schema scheam which is having anyOf
* @returns true if all the schemas which inside anyOf presents in matching schema
*/
function isAllSchemasMatched(node, matchingSchemas, schema) {
let count = 0;
for (const matchSchema of matchingSchemas) {
if (node === matchSchema.node && matchSchema.schema !== schema) {
schema.anyOf.forEach((childSchema) => {
if (matchSchema.schema.title === childSchema.title &&
matchSchema.schema.description === childSchema.description &&
matchSchema.schema.properties === childSchema.properties) {
count++;
}
});
}
}
return count === schema.anyOf.length;
}
//# sourceMappingURL=yamlHover.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
import { DocumentLink } from 'vscode-languageserver-types';
import { TextDocument } from 'vscode-languageserver-textdocument';
import { Telemetry } from '../telemetry';
export declare class YamlLinks {
private readonly telemetry?;
constructor(telemetry?: Telemetry);
findLinks(document: TextDocument): Promise<DocumentLink[]>;
}
@@ -0,0 +1,27 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { findLinks as JSONFindLinks } from 'vscode-json-languageservice/lib/umd/services/jsonLinks';
import { yamlDocumentsCache } from '../parser/yaml-documents';
export class YamlLinks {
constructor(telemetry) {
this.telemetry = telemetry;
}
findLinks(document) {
try {
const doc = yamlDocumentsCache.getYamlDocument(document);
// Find links across all YAML Documents then report them back once finished
const linkPromises = [];
for (const yamlDoc of doc.documents) {
linkPromises.push(JSONFindLinks(document, yamlDoc));
}
// Wait for all the promises to return and then flatten them into one DocumentLink array
return Promise.all(linkPromises).then((yamlLinkArray) => [].concat(...yamlLinkArray));
}
catch (err) {
this.telemetry?.sendError('yaml.documentLink.error', err);
}
}
}
//# sourceMappingURL=yamlLinks.js.map
@@ -0,0 +1 @@
{"version":3,"file":"yamlLinks.js","sourceRoot":"","sources":["../../../../src/languageservice/services/yamlLinks.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAChG,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,wDAAwD,CAAC;AAIpG,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,OAAO,SAAS;IACpB,YAA6B,SAAqB;QAArB,cAAS,GAAT,SAAS,CAAY;IAAG,CAAC;IAEtD,SAAS,CAAC,QAAsB;QAC9B,IAAI;YACF,MAAM,GAAG,GAAG,kBAAkB,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;YACzD,2EAA2E;YAC3E,MAAM,YAAY,GAAG,EAAE,CAAC;YACxB,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,SAAS,EAAE;gBACnC,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;aACrD;YACD,wFAAwF;YACxF,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;SACvF;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC;SAC3D;IACH,CAAC;CACF"}
@@ -0,0 +1,4 @@
import { DocumentOnTypeFormattingParams } from 'vscode-languageserver';
import { TextEdit } from 'vscode-languageserver-types';
import { TextDocument } from 'vscode-languageserver-textdocument';
export declare function doDocumentOnTypeFormatting(document: TextDocument, params: DocumentOnTypeFormattingParams): TextEdit[] | undefined;

Some files were not shown because too many files have changed in this diff Show More