mirror of
https://github.com/danbulant/monaco-yaml
synced 2026-07-08 20:40:46 +00:00
test: add jest for testing
This commit is contained in:
parent
7b140ccb4c
commit
cb10912b7e
10 changed files with 103 additions and 71 deletions
|
|
@ -72,7 +72,7 @@ function recursivelyBuildAst(parent: ASTNode, node: Yaml.YAMLNode): ASTNode {
|
||||||
// TODO: calculate the correct NULL range.
|
// TODO: calculate the correct NULL range.
|
||||||
const valueNode = instance.value
|
const valueNode = instance.value
|
||||||
? recursivelyBuildAst(result, instance.value)
|
? recursivelyBuildAst(result, instance.value)
|
||||||
: new NullASTNodeImpl(parent, instance.endPosition);
|
: new NullASTNodeImpl(result, instance.endPosition);
|
||||||
|
|
||||||
result.keyNode = keyNode;
|
result.keyNode = keyNode;
|
||||||
result.valueNode = valueNode;
|
result.valueNode = valueNode;
|
||||||
|
|
|
||||||
|
|
@ -556,7 +556,8 @@ export class JSONSchemaService implements IJSONSchemaService {
|
||||||
next.anyOf,
|
next.anyOf,
|
||||||
next.allOf,
|
next.allOf,
|
||||||
next.oneOf,
|
next.oneOf,
|
||||||
next.items as JSONSchema[]
|
next.items as JSONSchema[],
|
||||||
|
next.schemaSequence,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,22 +35,19 @@ import {
|
||||||
ClientCapabilities,
|
ClientCapabilities,
|
||||||
ObjectASTNode,
|
ObjectASTNode,
|
||||||
PropertyASTNode,
|
PropertyASTNode,
|
||||||
StringASTNode,
|
|
||||||
} from '../jsonLanguageTypes';
|
} from '../jsonLanguageTypes';
|
||||||
import { matchOffsetToDocument } from '../utils/arrUtils';
|
import { matchOffsetToDocument } from '../utils/arrUtils';
|
||||||
import { stringifyObject } from '../utils/json';
|
import { stringifyObject } from '../utils/json';
|
||||||
import { isDefined } from '../utils/objects';
|
import { isDefined } from '../utils/objects';
|
||||||
import { endsWith } from '../utils/strings';
|
import { endsWith } from '../utils/strings';
|
||||||
import { YAMLDocument } from '../yamlLanguageTypes';
|
import { YAMLDocument } from '../yamlLanguageTypes';
|
||||||
|
import { LanguageSettings } from '../yamlLanguageService';
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
// !! FIXME: this implementation is buggy
|
|
||||||
|
|
||||||
export class YAMLCompletion {
|
export class YAMLCompletion {
|
||||||
|
private completionEnabled = true;
|
||||||
private supportsMarkdown: boolean | undefined;
|
private supportsMarkdown: boolean | undefined;
|
||||||
|
|
||||||
private templateVarIdCounter = 0;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private schemaService: SchemaService.IJSONSchemaService,
|
private schemaService: SchemaService.IJSONSchemaService,
|
||||||
private contributions: JSONWorkerContribution[] = [],
|
private contributions: JSONWorkerContribution[] = [],
|
||||||
|
|
@ -60,6 +57,12 @@ export class YAMLCompletion {
|
||||||
this.contributions = contributions;
|
this.contributions = contributions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public configure(settings: LanguageSettings) {
|
||||||
|
if (settings) {
|
||||||
|
this.completionEnabled = settings.completion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public doResolve(item: CompletionItem): Thenable<CompletionItem> {
|
public doResolve(item: CompletionItem): Thenable<CompletionItem> {
|
||||||
for (let i = this.contributions.length - 1; i >= 0; i--) {
|
for (let i = this.contributions.length - 1; i >= 0; i--) {
|
||||||
if (this.contributions[i].resolveCompletion) {
|
if (this.contributions[i].resolveCompletion) {
|
||||||
|
|
@ -88,7 +91,7 @@ export class YAMLCompletion {
|
||||||
|
|
||||||
const currentDocIndex = doc.documents.indexOf(currentDoc);
|
const currentDocIndex = doc.documents.indexOf(currentDoc);
|
||||||
|
|
||||||
if (currentDoc === null) {
|
if (currentDoc === null || !this.completionEnabled) {
|
||||||
return Promise.resolve(result);
|
return Promise.resolve(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,60 +15,70 @@ import {
|
||||||
} from 'vscode-languageserver-types';
|
} from 'vscode-languageserver-types';
|
||||||
import { EOL } from '../../fillers/os';
|
import { EOL } from '../../fillers/os';
|
||||||
import * as Yaml from '../../yaml-ast-parser/index';
|
import * as Yaml from '../../yaml-ast-parser/index';
|
||||||
|
import { LanguageSettings } from '../yamlLanguageService';
|
||||||
|
|
||||||
export function format(
|
export class YamlFormatter {
|
||||||
document: TextDocument,
|
private customTags: string[];
|
||||||
options: FormattingOptions,
|
|
||||||
customTags: String[]
|
|
||||||
): TextEdit[] {
|
|
||||||
const text = document.getText();
|
|
||||||
customTags = customTags || [];
|
|
||||||
|
|
||||||
const schemaWithAdditionalTags = jsyaml.Schema.create(
|
configure(settings: LanguageSettings) {
|
||||||
customTags.map(tag => {
|
if (settings) {
|
||||||
const typeInfo = tag.split(' ');
|
this.customTags = settings.customTags || [];
|
||||||
return new jsyaml.Type(typeInfo[0], { kind: typeInfo[1] || 'scalar' });
|
}
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// We need compiledTypeMap to be available from schemaWithAdditionalTags before we add the new custom properties
|
|
||||||
customTags.map(tag => {
|
|
||||||
const typeInfo = tag.split(' ');
|
|
||||||
schemaWithAdditionalTags.compiledTypeMap[typeInfo[0]] = new jsyaml.Type(
|
|
||||||
typeInfo[0],
|
|
||||||
{ kind: typeInfo[1] || 'scalar' }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const additionalOptions: Yaml.LoadOptions = {
|
|
||||||
schema: schemaWithAdditionalTags,
|
|
||||||
};
|
|
||||||
|
|
||||||
const documents = [];
|
|
||||||
jsyaml.loadAll(text, doc => documents.push(doc), additionalOptions);
|
|
||||||
|
|
||||||
const dumpOptions = { indent: options.tabSize, noCompatMode: true };
|
|
||||||
|
|
||||||
let newText;
|
|
||||||
if (documents.length == 1) {
|
|
||||||
const yaml = documents[0];
|
|
||||||
newText = jsyaml.safeDump(yaml, dumpOptions);
|
|
||||||
} else {
|
|
||||||
const formatted = documents.map(d => jsyaml.safeDump(d, dumpOptions));
|
|
||||||
newText =
|
|
||||||
'%YAML 1.2' +
|
|
||||||
EOL +
|
|
||||||
'---' +
|
|
||||||
EOL +
|
|
||||||
formatted.join('...' + EOL + '---' + EOL) +
|
|
||||||
'...' +
|
|
||||||
EOL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
doFormat(
|
||||||
TextEdit.replace(
|
document: TextDocument,
|
||||||
Range.create(Position.create(0, 0), document.positionAt(text.length)),
|
options: FormattingOptions,
|
||||||
newText
|
): TextEdit[] {
|
||||||
),
|
const text = document.getText();
|
||||||
];
|
const customTags = this.customTags || [];
|
||||||
|
|
||||||
|
const schemaWithAdditionalTags = jsyaml.Schema.create(
|
||||||
|
customTags.map(tag => {
|
||||||
|
const typeInfo = tag.split(' ');
|
||||||
|
return new jsyaml.Type(typeInfo[0], { kind: typeInfo[1] || 'scalar' });
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// We need compiledTypeMap to be available from schemaWithAdditionalTags before we add the new custom properties
|
||||||
|
customTags.map(tag => {
|
||||||
|
const typeInfo = tag.split(' ');
|
||||||
|
schemaWithAdditionalTags.compiledTypeMap[typeInfo[0]] = new jsyaml.Type(
|
||||||
|
typeInfo[0],
|
||||||
|
{ kind: typeInfo[1] || 'scalar' }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const additionalOptions: Yaml.LoadOptions = {
|
||||||
|
schema: schemaWithAdditionalTags,
|
||||||
|
};
|
||||||
|
|
||||||
|
const documents = [];
|
||||||
|
jsyaml.loadAll(text, doc => documents.push(doc), additionalOptions);
|
||||||
|
|
||||||
|
const dumpOptions = { indent: options.tabSize, noCompatMode: true };
|
||||||
|
|
||||||
|
let newText;
|
||||||
|
if (documents.length == 1) {
|
||||||
|
const yaml = documents[0];
|
||||||
|
newText = jsyaml.safeDump(yaml, dumpOptions);
|
||||||
|
} else {
|
||||||
|
const formatted = documents.map(d => jsyaml.safeDump(d, dumpOptions));
|
||||||
|
newText =
|
||||||
|
'%YAML 1.2' +
|
||||||
|
EOL +
|
||||||
|
'---' +
|
||||||
|
EOL +
|
||||||
|
formatted.join('...' + EOL + '---' + EOL) +
|
||||||
|
'...' +
|
||||||
|
EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
TextEdit.replace(
|
||||||
|
Range.create(Position.create(0, 0), document.positionAt(text.length)),
|
||||||
|
newText
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,22 @@ import {
|
||||||
} from 'vscode-languageserver-types';
|
} from 'vscode-languageserver-types';
|
||||||
import { matchOffsetToDocument } from '../utils/arrUtils';
|
import { matchOffsetToDocument } from '../utils/arrUtils';
|
||||||
import { YAMLDocument } from '../yamlLanguageTypes';
|
import { YAMLDocument } from '../yamlLanguageTypes';
|
||||||
|
import { LanguageSettings } from '../yamlLanguageService';
|
||||||
|
|
||||||
export class YAMLHover {
|
export class YAMLHover {
|
||||||
|
private shouldHover = true;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private schemaService: SchemaService.IJSONSchemaService,
|
private schemaService: SchemaService.IJSONSchemaService,
|
||||||
private contributions: JSONWorkerContribution[] = []
|
private contributions: JSONWorkerContribution[] = []
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
public configure(languageSettings: LanguageSettings){
|
||||||
|
if(languageSettings){
|
||||||
|
this.shouldHover = !!languageSettings.hover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public doHover(
|
public doHover(
|
||||||
document: TextDocument,
|
document: TextDocument,
|
||||||
position: Position,
|
position: Position,
|
||||||
|
|
@ -33,11 +42,11 @@ export class YAMLHover {
|
||||||
): Thenable<Hover> {
|
): Thenable<Hover> {
|
||||||
const offset = document.offsetAt(position);
|
const offset = document.offsetAt(position);
|
||||||
const currentDoc = matchOffsetToDocument(offset, doc);
|
const currentDoc = matchOffsetToDocument(offset, doc);
|
||||||
if (currentDoc === null) {
|
if (currentDoc === null || !this.shouldHover) {
|
||||||
return Promise.resolve(void 0);
|
return Promise.resolve(void 0);
|
||||||
}
|
}
|
||||||
const currentDocIndex = doc.documents.indexOf(currentDoc);
|
|
||||||
let node = currentDoc.getNodeFromOffset(offset);
|
let node = currentDoc.getNodeFromOffset(offset);
|
||||||
|
const currentDocIndex = doc.documents.indexOf(currentDoc);
|
||||||
if (
|
if (
|
||||||
!node ||
|
!node ||
|
||||||
((node.type === 'object' || node.type === 'array') &&
|
((node.type === 'object' || node.type === 'array') &&
|
||||||
|
|
@ -85,8 +94,13 @@ export class YAMLHover {
|
||||||
.getSchemaForResource(document.uri, currentDoc)
|
.getSchemaForResource(document.uri, currentDoc)
|
||||||
.then(schema => {
|
.then(schema => {
|
||||||
if (schema) {
|
if (schema) {
|
||||||
|
let newSchema = schema;
|
||||||
|
if (schema.schema && schema.schema.schemaSequence && schema.schema.schemaSequence[currentDocIndex]) {
|
||||||
|
newSchema = new SchemaService.ResolvedSchema(schema.schema.schemaSequence[currentDocIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
const matchingSchemas = currentDoc.getMatchingSchemas(
|
const matchingSchemas = currentDoc.getMatchingSchemas(
|
||||||
schema.schema,
|
newSchema.schema,
|
||||||
node.offset
|
node.offset
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import {
|
||||||
JSONSchemaService,
|
JSONSchemaService,
|
||||||
} from './services/jsonSchemaService';
|
} from './services/jsonSchemaService';
|
||||||
import { YAMLCompletion } from './services/yamlCompletion';
|
import { YAMLCompletion } from './services/yamlCompletion';
|
||||||
import { format } from './services/yamlFormatter';
|
import { YamlFormatter } from './services/yamlFormatter';
|
||||||
import { YAMLHover } from './services/yamlHover';
|
import { YAMLHover } from './services/yamlHover';
|
||||||
import { YAMLValidation } from './services/yamlValidation';
|
import { YAMLValidation } from './services/yamlValidation';
|
||||||
import { YAMLDocument } from './yamlLanguageTypes';
|
import { YAMLDocument } from './yamlLanguageTypes';
|
||||||
|
|
@ -38,7 +38,7 @@ export interface LanguageSettings {
|
||||||
completion?: boolean; // Setting for whether we want to have completion results
|
completion?: boolean; // Setting for whether we want to have completion results
|
||||||
isKubernetes?: boolean; // If true then its validating against kubernetes
|
isKubernetes?: boolean; // If true then its validating against kubernetes
|
||||||
schemas?: any[]; // List of schemas,
|
schemas?: any[]; // List of schemas,
|
||||||
customTags?: String[]; // Array of Custom Tags
|
customTags?: string[]; // Array of Custom Tags
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Thenable<R> {
|
export interface Thenable<R> {
|
||||||
|
|
@ -134,6 +134,7 @@ export function getLanguageService(
|
||||||
const hover = new YAMLHover(schemaService, contributions);
|
const hover = new YAMLHover(schemaService, contributions);
|
||||||
const yamlDocumentSymbols = new YAMLDocumentSymbols(schemaService);
|
const yamlDocumentSymbols = new YAMLDocumentSymbols(schemaService);
|
||||||
const yamlValidation = new YAMLValidation(schemaService);
|
const yamlValidation = new YAMLValidation(schemaService);
|
||||||
|
const yamlFormatter = new YamlFormatter();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
configure: settings => {
|
configure: settings => {
|
||||||
|
|
@ -147,6 +148,11 @@ export function getLanguageService(
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
yamlValidation.configure(settings);
|
||||||
|
hover.configure(settings);
|
||||||
|
completer.configure(settings);
|
||||||
|
yamlFormatter.configure(settings);
|
||||||
},
|
},
|
||||||
registerCustomSchemaProvider: (schemaProvider: CustomSchemaProvider) => {
|
registerCustomSchemaProvider: (schemaProvider: CustomSchemaProvider) => {
|
||||||
schemaService.registerCustomSchemaProvider(schemaProvider);
|
schemaService.registerCustomSchemaProvider(schemaProvider);
|
||||||
|
|
@ -165,7 +171,7 @@ export function getLanguageService(
|
||||||
yamlDocumentSymbols
|
yamlDocumentSymbols
|
||||||
),
|
),
|
||||||
resetSchema: (uri: string) => schemaService.onResourceChange(uri),
|
resetSchema: (uri: string) => schemaService.onResourceChange(uri),
|
||||||
doFormat: format,
|
doFormat: yamlFormatter.doFormat.bind(yamlFormatter),
|
||||||
parseYAMLDocument: (document: TextDocument) =>
|
parseYAMLDocument: (document: TextDocument) =>
|
||||||
parseYAML(document.getText()),
|
parseYAML(document.getText()),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ describe('Auto Completion Tests', () => {
|
||||||
|
|
||||||
function parseSetup(content: string, position) {
|
function parseSetup(content: string, position) {
|
||||||
const testTextDocument = setup(content);
|
const testTextDocument = setup(content);
|
||||||
const yDoc = parseYAML(testTextDocument.getText());
|
|
||||||
return completionHelper(
|
return completionHelper(
|
||||||
testTextDocument,
|
testTextDocument,
|
||||||
testTextDocument.positionAt(position),
|
testTextDocument.positionAt(position),
|
||||||
|
|
@ -70,7 +69,7 @@ describe('Auto Completion Tests', () => {
|
||||||
const completion = parseSetup(content, 12);
|
const completion = parseSetup(content, 12);
|
||||||
completion
|
completion
|
||||||
.then(function (result) {
|
.then(function (result) {
|
||||||
expect(result.items.length).toEqual(0);
|
expect(result.items.length).toEqual(1);
|
||||||
})
|
})
|
||||||
.then(done, done);
|
.then(done, done);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ describe('Formatter Tests', () => {
|
||||||
assert.equal(edits[0].newText, 'cwd: test\n');
|
assert.equal(edits[0].newText, 'cwd: test\n');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Formatting works without custom tags', () => {
|
it('Formatting works with custom tags', () => {
|
||||||
const content = `cwd: !Test test`;
|
const content = `cwd: !Test test`;
|
||||||
const testTextDocument = setup(content);
|
const testTextDocument = setup(content);
|
||||||
const edits = languageService.doFormat(
|
const edits = languageService.doFormat(
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ describe('Hover Setting Tests', () => {
|
||||||
const hover = parseSetup(content, 1);
|
const hover = parseSetup(content, 1);
|
||||||
hover
|
hover
|
||||||
.then(function (result) {
|
.then(function (result) {
|
||||||
assert.notEqual(result, undefined);
|
assert.equal(result, undefined);
|
||||||
})
|
})
|
||||||
.then(done, done);
|
.then(done, done);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"lib": ["es2016"],
|
"lib": ["es2016"],
|
||||||
"outDir": "./out/server",
|
|
||||||
"downlevelIteration": true
|
"downlevelIteration": true
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules", "out"]
|
"exclude": ["node_modules", "out"]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue