fix: add colon position to key node

This commit is contained in:
Peng Xiao 2018-12-18 18:49:13 +08:00
parent 84e82b52f7
commit ed907a9096
10 changed files with 206 additions and 16 deletions

18
.vscode/launch.json vendored Normal file
View 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"
}
]
}

View file

@ -142,6 +142,7 @@ export class NumberASTNodeImpl extends ASTNodeImpl implements NumberASTNode {
export class StringASTNodeImpl extends ASTNodeImpl implements StringASTNode {
public type: 'string' = 'string';
public value: string;
public isKey: boolean;
constructor(parent: ASTNode, offset: number, length?: number) {
super(parent, offset, length);

View file

@ -61,6 +61,8 @@ function recursivelyBuildAst(parent: ASTNode, node: Yaml.YAMLNode): ASTNode {
instance.endPosition - key.startPosition
);
result.colonOffset = key.colonPosition;
// Technically, this is an arbitrary node in YAML
// I doubt we would get a better string representation by parsing it
const keyNode = new StringASTNodeImpl(
@ -69,6 +71,7 @@ function recursivelyBuildAst(parent: ASTNode, node: Yaml.YAMLNode): ASTNode {
key.endPosition - key.startPosition
);
keyNode.value = key.value;
keyNode.isKey = true;
// TODO: calculate the correct NULL range.
const valueNode = instance.value

View file

@ -59,7 +59,7 @@ export class YAMLCompletion {
public configure(settings: LanguageSettings) {
if (settings) {
this.completionEnabled = settings.completion;
this.completionEnabled = settings.completion !== false;
}
}

View file

@ -31,7 +31,7 @@ export class YAMLHover {
public configure(languageSettings: LanguageSettings) {
if (languageSettings) {
this.shouldHover = !!languageSettings.hover;
this.shouldHover = languageSettings.hover !== false;
}
}

View file

@ -23,7 +23,7 @@ export class YAMLValidation {
public configure(raw: LanguageSettings) {
if (raw) {
this.validationEnabled = raw.validate;
this.validationEnabled = raw.validate !== false;
}
}

View file

@ -1,8 +1,9 @@
import { ASTNode } from './jsonLanguageTypes';
import { JSONDocument, IProblem } from './parser/jsonParser';
import { getPosition } from './utils/documentPositionCalculator';
export class SingleYAMLDocument extends JSONDocument {
public lines;
public lines: number[];
public errors: IProblem[];
public warnings: IProblem[];
@ -23,6 +24,116 @@ export class SingleYAMLDocument extends JSONDocument {
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 {
const collector: ASTNode[] = [];
const findNode = (node: ASTNode): ASTNode => {
@ -60,12 +171,8 @@ export class SingleYAMLDocument extends JSONDocument {
export class YAMLDocument {
public documents: SingleYAMLDocument[];
public errors;
public warnings;
constructor(documents: SingleYAMLDocument[]) {
this.documents = documents;
this.errors = [];
this.warnings = [];
}
}

View file

@ -492,11 +492,7 @@ function storeMappingPair(
});
_result.mappings.push(mapping);
_result.endPosition = valueNode
? valueNode.endPosition
: keyNode.endPosition + 1; // FIXME.workaround should be position of ':' indeed
// }
_result.endPosition = mapping.endPosition;
return _result;
}
@ -646,7 +642,8 @@ function readPlainScalar(state: State, nodeIndent, withinFlowCollection) {
_lineIndent,
_kind = state.kind,
_result = state.result,
ch;
ch,
_colonPosition = -1;
const state_result = ast.newScalar();
state_result.plainScalar = true;
state.result = state_result;
@ -694,6 +691,7 @@ function readPlainScalar(state: State, nodeIndent, withinFlowCollection) {
is_WS_OR_EOL(following) ||
(withinFlowCollection && is_FLOW_INDICATOR(following))
) {
_colonPosition = state.position;
break;
}
} else if (0x23 /* # */ === ch) {
@ -750,6 +748,7 @@ function readPlainScalar(state: State, nodeIndent, withinFlowCollection) {
state_result.startPosition,
state_result.endPosition
);
state_result.colonPosition = _colonPosition;
return true;
}

View file

@ -20,6 +20,7 @@ export interface YAMLNode extends YAMLDocument {
startPosition: number;
endPosition: number;
kind: Kind;
colonPosition?: number; // Nearest colon position.
anchorId?: string;
valueObject?: any;
parent: YAMLNode;
@ -63,8 +64,7 @@ export interface YamlMap extends YAMLNode {
mappings: 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 ':'
// console.log('key: ' + key.value + ' ' + key.startPosition + '..' + key.endPosition + ' ' + value + ' end: ' + end);
const end = value ? value.endPosition : key.colonPosition + 1;
const node = {
key,
value,

62
test/yamlDocument.test.ts Normal file
View 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');
});
});
});