mirror of
https://github.com/danbulant/monaco-yaml
synced 2026-06-09 17:41:32 +00:00
fix: add colon position to key node
This commit is contained in:
parent
84e82b52f7
commit
ed907a9096
10 changed files with 206 additions and 16 deletions
18
.vscode/launch.json
vendored
Normal file
18
.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"name": "vscode-jest-tests",
|
||||||
|
"request": "launch",
|
||||||
|
"args": ["--runInBand"],
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"internalConsoleOptions": "neverOpen",
|
||||||
|
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -142,6 +142,7 @@ export class NumberASTNodeImpl extends ASTNodeImpl implements NumberASTNode {
|
||||||
export class StringASTNodeImpl extends ASTNodeImpl implements StringASTNode {
|
export class StringASTNodeImpl extends ASTNodeImpl implements StringASTNode {
|
||||||
public type: 'string' = 'string';
|
public type: 'string' = 'string';
|
||||||
public value: string;
|
public value: string;
|
||||||
|
public isKey: boolean;
|
||||||
|
|
||||||
constructor(parent: ASTNode, offset: number, length?: number) {
|
constructor(parent: ASTNode, offset: number, length?: number) {
|
||||||
super(parent, offset, length);
|
super(parent, offset, length);
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,8 @@ function recursivelyBuildAst(parent: ASTNode, node: Yaml.YAMLNode): ASTNode {
|
||||||
instance.endPosition - key.startPosition
|
instance.endPosition - key.startPosition
|
||||||
);
|
);
|
||||||
|
|
||||||
|
result.colonOffset = key.colonPosition;
|
||||||
|
|
||||||
// Technically, this is an arbitrary node in YAML
|
// Technically, this is an arbitrary node in YAML
|
||||||
// I doubt we would get a better string representation by parsing it
|
// I doubt we would get a better string representation by parsing it
|
||||||
const keyNode = new StringASTNodeImpl(
|
const keyNode = new StringASTNodeImpl(
|
||||||
|
|
@ -69,6 +71,7 @@ function recursivelyBuildAst(parent: ASTNode, node: Yaml.YAMLNode): ASTNode {
|
||||||
key.endPosition - key.startPosition
|
key.endPosition - key.startPosition
|
||||||
);
|
);
|
||||||
keyNode.value = key.value;
|
keyNode.value = key.value;
|
||||||
|
keyNode.isKey = true;
|
||||||
|
|
||||||
// TODO: calculate the correct NULL range.
|
// TODO: calculate the correct NULL range.
|
||||||
const valueNode = instance.value
|
const valueNode = instance.value
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ export class YAMLCompletion {
|
||||||
|
|
||||||
public configure(settings: LanguageSettings) {
|
public configure(settings: LanguageSettings) {
|
||||||
if (settings) {
|
if (settings) {
|
||||||
this.completionEnabled = settings.completion;
|
this.completionEnabled = settings.completion !== false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ export class YAMLHover {
|
||||||
|
|
||||||
public configure(languageSettings: LanguageSettings) {
|
public configure(languageSettings: LanguageSettings) {
|
||||||
if (languageSettings) {
|
if (languageSettings) {
|
||||||
this.shouldHover = !!languageSettings.hover;
|
this.shouldHover = languageSettings.hover !== false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ export class YAMLValidation {
|
||||||
|
|
||||||
public configure(raw: LanguageSettings) {
|
public configure(raw: LanguageSettings) {
|
||||||
if (raw) {
|
if (raw) {
|
||||||
this.validationEnabled = raw.validate;
|
this.validationEnabled = raw.validate !== false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import { ASTNode } from './jsonLanguageTypes';
|
import { ASTNode } from './jsonLanguageTypes';
|
||||||
import { JSONDocument, IProblem } from './parser/jsonParser';
|
import { JSONDocument, IProblem } from './parser/jsonParser';
|
||||||
|
import { getPosition } from './utils/documentPositionCalculator';
|
||||||
|
|
||||||
export class SingleYAMLDocument extends JSONDocument {
|
export class SingleYAMLDocument extends JSONDocument {
|
||||||
public lines;
|
public lines: number[];
|
||||||
public errors: IProblem[];
|
public errors: IProblem[];
|
||||||
public warnings: IProblem[];
|
public warnings: IProblem[];
|
||||||
|
|
||||||
|
|
@ -23,6 +24,116 @@ export class SingleYAMLDocument extends JSONDocument {
|
||||||
return super.getNodeFromOffset(offset, true);
|
return super.getNodeFromOffset(offset, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getNodeFromOffsetEndInclusive(offset: number): ASTNode {
|
||||||
|
// if (!this.root) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// if (
|
||||||
|
// offset < this.root.offset ||
|
||||||
|
// offset > this.root.offset + this.root.length
|
||||||
|
// ) {
|
||||||
|
// // We somehow are completely outside the document
|
||||||
|
// // This is unexpected
|
||||||
|
// console.log('Attempting to resolve node outside of document');
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// function* sliding2(nodes: ASTNode[]) {
|
||||||
|
// for (let i = 0; i < nodes.length; i ++) {
|
||||||
|
// yield [nodes[i], i === nodes.length ? null : nodes[i + 1]];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const onLaterLine = (offset: number, node: ASTNode) => {
|
||||||
|
// const { line: actualLine } = getPosition(offset, this.lines);
|
||||||
|
// const { line: nodeEndLine } = getPosition(
|
||||||
|
// node.offset + node.length,
|
||||||
|
// this.lines
|
||||||
|
// );
|
||||||
|
|
||||||
|
// return actualLine > nodeEndLine;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let findNode = (nodes: ASTNode[]): ASTNode => {
|
||||||
|
// if (nodes.length === 0) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const gen = sliding2(nodes);
|
||||||
|
|
||||||
|
// for (let [first, second] of gen) {
|
||||||
|
// const end = second
|
||||||
|
// ? second.offset
|
||||||
|
// : first.parent.offset + first.parent.length;
|
||||||
|
// if (offset >= first.offset && offset < end) {
|
||||||
|
// const children = first.children;
|
||||||
|
|
||||||
|
// const foundChild = findNode(children);
|
||||||
|
|
||||||
|
// if (!foundChild && onLaterLine(offset, first)) {
|
||||||
|
// return this.getNodeByIndent(this.lines, offset, this.root);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return foundChild || first;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return null;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return findNode(this.root.children) || this.root;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private getNodeByIndent = (
|
||||||
|
// lines: number[],
|
||||||
|
// offset: number,
|
||||||
|
// node: ASTNode
|
||||||
|
// ) => {
|
||||||
|
// const { line, column: indent } = getPosition(offset, this.lines);
|
||||||
|
|
||||||
|
// const children = node.children;
|
||||||
|
|
||||||
|
// function findNode(children: ASTNode[]) {
|
||||||
|
// if (children.length > 0) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// for (let idx = 0; idx < children.length; idx++) {
|
||||||
|
// const child = children[idx];
|
||||||
|
|
||||||
|
// const { line: childLine, column: childCol } = getPosition(
|
||||||
|
// child.offset,
|
||||||
|
// lines
|
||||||
|
// );
|
||||||
|
|
||||||
|
// if (childCol > indent) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const newChildren = child.children;
|
||||||
|
// const foundNode = findNode(newChildren);
|
||||||
|
|
||||||
|
// if (foundNode) {
|
||||||
|
// return foundNode;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // We have the right indentation, need to return based on line
|
||||||
|
// if (childLine == line) {
|
||||||
|
// return child;
|
||||||
|
// }
|
||||||
|
// if (childLine > line) {
|
||||||
|
// // Get previous
|
||||||
|
// idx - 1 >= 0 ? children[idx - 1] : child;
|
||||||
|
// }
|
||||||
|
// // Else continue loop to try next element
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Special case, we found the correct
|
||||||
|
// return children[children.length - 1];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return findNode(children) || node;
|
||||||
|
// };
|
||||||
|
|
||||||
public getNodeFromOffsetEndInclusive(offset: number): ASTNode {
|
public getNodeFromOffsetEndInclusive(offset: number): ASTNode {
|
||||||
const collector: ASTNode[] = [];
|
const collector: ASTNode[] = [];
|
||||||
const findNode = (node: ASTNode): ASTNode => {
|
const findNode = (node: ASTNode): ASTNode => {
|
||||||
|
|
@ -60,12 +171,8 @@ export class SingleYAMLDocument extends JSONDocument {
|
||||||
|
|
||||||
export class YAMLDocument {
|
export class YAMLDocument {
|
||||||
public documents: SingleYAMLDocument[];
|
public documents: SingleYAMLDocument[];
|
||||||
public errors;
|
|
||||||
public warnings;
|
|
||||||
|
|
||||||
constructor(documents: SingleYAMLDocument[]) {
|
constructor(documents: SingleYAMLDocument[]) {
|
||||||
this.documents = documents;
|
this.documents = documents;
|
||||||
this.errors = [];
|
|
||||||
this.warnings = [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -492,11 +492,7 @@ function storeMappingPair(
|
||||||
});
|
});
|
||||||
|
|
||||||
_result.mappings.push(mapping);
|
_result.mappings.push(mapping);
|
||||||
_result.endPosition = valueNode
|
_result.endPosition = mapping.endPosition;
|
||||||
? valueNode.endPosition
|
|
||||||
: keyNode.endPosition + 1; // FIXME.workaround should be position of ':' indeed
|
|
||||||
// }
|
|
||||||
|
|
||||||
return _result;
|
return _result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -646,7 +642,8 @@ function readPlainScalar(state: State, nodeIndent, withinFlowCollection) {
|
||||||
_lineIndent,
|
_lineIndent,
|
||||||
_kind = state.kind,
|
_kind = state.kind,
|
||||||
_result = state.result,
|
_result = state.result,
|
||||||
ch;
|
ch,
|
||||||
|
_colonPosition = -1;
|
||||||
const state_result = ast.newScalar();
|
const state_result = ast.newScalar();
|
||||||
state_result.plainScalar = true;
|
state_result.plainScalar = true;
|
||||||
state.result = state_result;
|
state.result = state_result;
|
||||||
|
|
@ -694,6 +691,7 @@ function readPlainScalar(state: State, nodeIndent, withinFlowCollection) {
|
||||||
is_WS_OR_EOL(following) ||
|
is_WS_OR_EOL(following) ||
|
||||||
(withinFlowCollection && is_FLOW_INDICATOR(following))
|
(withinFlowCollection && is_FLOW_INDICATOR(following))
|
||||||
) {
|
) {
|
||||||
|
_colonPosition = state.position;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (0x23 /* # */ === ch) {
|
} else if (0x23 /* # */ === ch) {
|
||||||
|
|
@ -750,6 +748,7 @@ function readPlainScalar(state: State, nodeIndent, withinFlowCollection) {
|
||||||
state_result.startPosition,
|
state_result.startPosition,
|
||||||
state_result.endPosition
|
state_result.endPosition
|
||||||
);
|
);
|
||||||
|
state_result.colonPosition = _colonPosition;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ export interface YAMLNode extends YAMLDocument {
|
||||||
startPosition: number;
|
startPosition: number;
|
||||||
endPosition: number;
|
endPosition: number;
|
||||||
kind: Kind;
|
kind: Kind;
|
||||||
|
colonPosition?: number; // Nearest colon position.
|
||||||
anchorId?: string;
|
anchorId?: string;
|
||||||
valueObject?: any;
|
valueObject?: any;
|
||||||
parent: YAMLNode;
|
parent: YAMLNode;
|
||||||
|
|
@ -63,8 +64,7 @@ export interface YamlMap extends YAMLNode {
|
||||||
mappings: YAMLMapping[];
|
mappings: YAMLMapping[];
|
||||||
}
|
}
|
||||||
export function newMapping(key: YAMLScalar, value: YAMLNode): YAMLMapping {
|
export function newMapping(key: YAMLScalar, value: YAMLNode): YAMLMapping {
|
||||||
const end = value ? value.endPosition : key.endPosition + 1; // FIXME.workaround, end should be defied by position of ':'
|
const end = value ? value.endPosition : key.colonPosition + 1;
|
||||||
// console.log('key: ' + key.value + ' ' + key.startPosition + '..' + key.endPosition + ' ' + value + ' end: ' + end);
|
|
||||||
const node = {
|
const node = {
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
|
|
|
||||||
62
test/yamlDocument.test.ts
Normal file
62
test/yamlDocument.test.ts
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
import { TextDocument } from 'vscode-languageserver';
|
||||||
|
import { parse as parseYAML } from '../src/languageservice/parser/yamlParser';
|
||||||
|
|
||||||
|
describe('SingleYAMLDocument tests', () => {
|
||||||
|
function setup(content: string) {
|
||||||
|
return TextDocument.create(
|
||||||
|
'file://~/Desktop/vscode-k8s/test.yaml',
|
||||||
|
'yaml',
|
||||||
|
0,
|
||||||
|
content
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('getNodeFromOffsetEndInclusive', () => {
|
||||||
|
const content = `a :
|
||||||
|
b:
|
||||||
|
|
||||||
|
`;
|
||||||
|
function parseSetup(offset: number) {
|
||||||
|
const yamlDocs = parseYAML(content);
|
||||||
|
|
||||||
|
// Should be one doc only
|
||||||
|
expect(yamlDocs.documents.length).toBe(1);
|
||||||
|
return yamlDocs.documents[0].getNodeFromOffsetEndInclusive(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
it('0', () => {
|
||||||
|
const node = parseSetup(0);
|
||||||
|
expect(node.value).toBe('a');
|
||||||
|
expect(node.type).toBe('string');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('1', () => {
|
||||||
|
const node = parseSetup(1);
|
||||||
|
expect(node.value).toBe('a');
|
||||||
|
expect(node.type).toBe('string');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('2', () => {
|
||||||
|
const node = parseSetup(2);
|
||||||
|
expect(node.type).toBe('property');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('6', () => {
|
||||||
|
const node = parseSetup(6);
|
||||||
|
expect(node.value).toBe('b');
|
||||||
|
expect(node.type).toBe('string');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('7', () => {
|
||||||
|
const node = parseSetup(7);
|
||||||
|
expect(node.value).toBe('b');
|
||||||
|
expect(node.type).toBe('string');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('8', () => {
|
||||||
|
const node = parseSetup(8);
|
||||||
|
expect(node.value).toBe('b');
|
||||||
|
expect(node.type).toBe('string');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue