mirror of
https://github.com/danbulant/monaco-yaml
synced 2026-07-05 19:10:58 +00:00
Convert json implementation to yaml libs
This commit is contained in:
parent
8ba88be05d
commit
ad350d08b2
11 changed files with 255 additions and 227 deletions
52
gulpfile.js
52
gulpfile.js
|
|
@ -14,8 +14,8 @@ var uglify = require('gulp-uglify');
|
||||||
var rimraf = require('rimraf');
|
var rimraf = require('rimraf');
|
||||||
var es = require('event-stream');
|
var es = require('event-stream');
|
||||||
|
|
||||||
gulp.task('clean-release', function(cb) { rimraf('release', { maxBusyTries: 1 }, cb); });
|
gulp.task('clean-release', function (cb) { rimraf('release', { maxBusyTries: 1 }, cb); });
|
||||||
gulp.task('release', ['clean-release','compile'], function() {
|
gulp.task('release', ['clean-release', 'compile'], function () {
|
||||||
|
|
||||||
var sha1 = getGitVersion(__dirname);
|
var sha1 = getGitVersion(__dirname);
|
||||||
var semver = require('./package.json').version;
|
var semver = require('./package.json').version;
|
||||||
|
|
@ -52,21 +52,13 @@ gulp.task('release', ['clean-release','compile'], function() {
|
||||||
|
|
||||||
return rjs({
|
return rjs({
|
||||||
baseUrl: '/out/',
|
baseUrl: '/out/',
|
||||||
name: 'vs/language/json/' + moduleId,
|
name: 'hl/yaml/' + moduleId,
|
||||||
out: moduleId + '.js',
|
out: moduleId + '.js',
|
||||||
exclude: exclude,
|
exclude: exclude,
|
||||||
paths: {
|
paths: {
|
||||||
'vs/language/json': __dirname + '/out'
|
'hl/yaml': __dirname + '/out'
|
||||||
},
|
},
|
||||||
packages: [{
|
packages: [{
|
||||||
name: 'vscode-yaml-languageservice',
|
|
||||||
location: __dirname + '/out/vscode-yaml-languageservice/',
|
|
||||||
main: 'yamlLanguageService'
|
|
||||||
}, {
|
|
||||||
name: 'yaml-language-server',
|
|
||||||
location: __dirname + '/out/yaml-language-server',
|
|
||||||
main: 'yamlLanguageService'
|
|
||||||
}, {
|
|
||||||
name: 'yaml-ast-parser',
|
name: 'yaml-ast-parser',
|
||||||
location: __dirname + '/out/yaml-ast-parser',
|
location: __dirname + '/out/yaml-ast-parser',
|
||||||
main: 'index'
|
main: 'index'
|
||||||
|
|
@ -108,22 +100,22 @@ gulp.task('release', ['clean-release','compile'], function() {
|
||||||
|
|
||||||
return merge(
|
return merge(
|
||||||
merge(
|
merge(
|
||||||
bundleOne('monaco.contribution', ['vs/language/json/jsonMode']),
|
bundleOne('monaco.contribution', ['hl/yaml/yamlMode']),
|
||||||
bundleOne('jsonMode'),
|
bundleOne('yamlMode'),
|
||||||
bundleOne('jsonWorker')
|
bundleOne('yamlWorker')
|
||||||
)
|
)
|
||||||
.pipe(es.through(function(data) {
|
.pipe(es.through(function (data) {
|
||||||
data.contents = new Buffer(
|
data.contents = new Buffer(
|
||||||
BUNDLED_FILE_HEADER
|
BUNDLED_FILE_HEADER
|
||||||
+ data.contents.toString()
|
+ data.contents.toString()
|
||||||
);
|
);
|
||||||
this.emit('data', data);
|
this.emit('data', data);
|
||||||
}))
|
}))
|
||||||
.pipe(gulp.dest('./release/dev'))
|
.pipe(gulp.dest('./release/dev'))
|
||||||
.pipe(uglify({
|
.pipe(uglify({
|
||||||
preserveComments: 'some'
|
preserveComments: 'some'
|
||||||
}))
|
}))
|
||||||
.pipe(gulp.dest('./release/min')),
|
.pipe(gulp.dest('./release/min')),
|
||||||
gulp.src('src/monaco.d.ts').pipe(gulp.dest('./release/min'))
|
gulp.src('src/monaco.d.ts').pipe(gulp.dest('./release/min'))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
@ -137,13 +129,13 @@ function compileTask() {
|
||||||
return merge(
|
return merge(
|
||||||
gulp.src(tsSources).pipe(compilation())
|
gulp.src(tsSources).pipe(compilation())
|
||||||
)
|
)
|
||||||
.pipe(gulp.dest('out'));
|
.pipe(gulp.dest('out'));
|
||||||
}
|
}
|
||||||
|
|
||||||
gulp.task('clean-out', function(cb) { rimraf('out', { maxBusyTries: 1 }, cb); });
|
gulp.task('clean-out', function (cb) { rimraf('out', { maxBusyTries: 1 }, cb); });
|
||||||
gulp.task('compile', ['clean-out'], compileTask);
|
gulp.task('compile', ['clean-out'], compileTask);
|
||||||
gulp.task('compile-without-clean', compileTask);
|
gulp.task('compile-without-clean', compileTask);
|
||||||
gulp.task('watch', ['compile'], function() {
|
gulp.task('watch', ['compile'], function () {
|
||||||
gulp.watch(tsSources, ['compile-without-clean']);
|
gulp.watch(tsSources, ['compile-without-clean']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "monaco-json",
|
"name": "monaco-yaml",
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"description": "JSON plugin for the Monaco Editor",
|
"description": "JSON plugin for the Monaco Editor",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import Promise = monaco.Promise;
|
|
||||||
import Thenable = monaco.Thenable;
|
|
||||||
import IWorkerContext = monaco.worker.IWorkerContext;
|
|
||||||
|
|
||||||
import * as jsonService from 'vscode-json-languageservice';
|
|
||||||
import * as ls from 'vscode-languageserver-types';
|
|
||||||
|
|
||||||
class PromiseAdapter<T> implements jsonService.Thenable<T> {
|
|
||||||
private wrapped: monaco.Promise<T>;
|
|
||||||
|
|
||||||
constructor(executor: (resolve: (value?: T | jsonService.Thenable<T>) => void, reject: (reason?: any) => void) => void) {
|
|
||||||
this.wrapped = new monaco.Promise<T>(executor);
|
|
||||||
}
|
|
||||||
public then<TResult>(onfulfilled?: (value: T) => TResult | jsonService.Thenable<TResult>, onrejected?: (reason: any) => void): jsonService.Thenable<TResult> {
|
|
||||||
let thenable : monaco.Thenable<T> = this.wrapped;
|
|
||||||
return thenable.then(onfulfilled, onrejected);
|
|
||||||
}
|
|
||||||
public getWrapped(): monaco.Thenable<T> {
|
|
||||||
return this.wrapped;
|
|
||||||
}
|
|
||||||
public cancel(): void {
|
|
||||||
this.wrapped.cancel();
|
|
||||||
}
|
|
||||||
public static resolve<T>(v: T | Thenable<T>): jsonService.Thenable<T> {
|
|
||||||
return <monaco.Thenable<T>> monaco.Promise.as(v);
|
|
||||||
}
|
|
||||||
public static reject<T>(v: T): jsonService.Thenable<T> {
|
|
||||||
return monaco.Promise.wrapError(v);
|
|
||||||
}
|
|
||||||
public static all<T>(values: jsonService.Thenable<T>[]): jsonService.Thenable<T[]> {
|
|
||||||
return monaco.Promise.join(values);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function toMonacoPromise<R>(thenable: jsonService.Thenable<R>): Thenable<R> {
|
|
||||||
if (thenable instanceof PromiseAdapter) {
|
|
||||||
return thenable.getWrapped();
|
|
||||||
}
|
|
||||||
return thenable;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class JSONWorker {
|
|
||||||
|
|
||||||
private _ctx: IWorkerContext;
|
|
||||||
private _languageService: jsonService.LanguageService;
|
|
||||||
private _languageSettings: jsonService.LanguageSettings;
|
|
||||||
private _languageId: string;
|
|
||||||
|
|
||||||
constructor(ctx: IWorkerContext, createData: ICreateData) {
|
|
||||||
this._ctx = ctx;
|
|
||||||
this._languageSettings = createData.languageSettings;
|
|
||||||
this._languageId = createData.languageId;
|
|
||||||
this._languageService = jsonService.getLanguageService({ promiseConstructor: PromiseAdapter });
|
|
||||||
this._languageService.configure(this._languageSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
doValidation(uri: string): Thenable<ls.Diagnostic[]> {
|
|
||||||
let document = this._getTextDocument(uri);
|
|
||||||
if (document) {
|
|
||||||
let jsonDocument = this._languageService.parseJSONDocument(document);
|
|
||||||
return this._languageService.doValidation(document, jsonDocument);
|
|
||||||
}
|
|
||||||
return Promise.as([]);
|
|
||||||
}
|
|
||||||
doComplete(uri: string, position: ls.Position): Thenable<ls.CompletionList> {
|
|
||||||
let document = this._getTextDocument(uri);
|
|
||||||
let jsonDocument = this._languageService.parseJSONDocument(document);
|
|
||||||
return this._languageService.doComplete(document, position, jsonDocument);
|
|
||||||
}
|
|
||||||
doResolve(item: ls.CompletionItem): Thenable<ls.CompletionItem> {
|
|
||||||
return this._languageService.doResolve(item);
|
|
||||||
}
|
|
||||||
doHover(uri: string, position: ls.Position): Thenable<ls.Hover> {
|
|
||||||
let document = this._getTextDocument(uri);
|
|
||||||
let jsonDocument = this._languageService.parseJSONDocument(document);
|
|
||||||
return this._languageService.doHover(document, position, jsonDocument);
|
|
||||||
}
|
|
||||||
format(uri: string, range: ls.Range, options: ls.FormattingOptions): Thenable<ls.TextEdit[]> {
|
|
||||||
let document = this._getTextDocument(uri);
|
|
||||||
let textEdits = this._languageService.format(document, range, options);
|
|
||||||
return Promise.as(textEdits);
|
|
||||||
}
|
|
||||||
resetSchema(uri: string): Thenable<boolean> {
|
|
||||||
return Promise.as(this._languageService.resetSchema(uri));
|
|
||||||
}
|
|
||||||
findDocumentSymbols(uri: string): Promise<ls.SymbolInformation[]> {
|
|
||||||
let document = this._getTextDocument(uri);
|
|
||||||
let jsonDocument = this._languageService.parseJSONDocument(document);
|
|
||||||
let symbols = this._languageService.findDocumentSymbols(document, jsonDocument);
|
|
||||||
return Promise.as(symbols);
|
|
||||||
}
|
|
||||||
private _getTextDocument(uri: string): ls.TextDocument {
|
|
||||||
let models = this._ctx.getMirrorModels();
|
|
||||||
for (let model of models) {
|
|
||||||
if (model.uri.toString() === uri) {
|
|
||||||
return ls.TextDocument.create(uri, this._languageId, model.version, model.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ICreateData {
|
|
||||||
languageId: string;
|
|
||||||
languageSettings: jsonService.LanguageSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function create(ctx: IWorkerContext, createData: ICreateData): JSONWorker {
|
|
||||||
return new JSONWorker(ctx, createData);
|
|
||||||
}
|
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import {LanguageServiceDefaultsImpl} from './monaco.contribution';
|
import { LanguageServiceDefaultsImpl } from './monaco.contribution';
|
||||||
import {JSONWorker} from './jsonWorker';
|
import { YAMLWorker } from './yamlWorker';
|
||||||
|
|
||||||
import * as ls from 'vscode-languageserver-types';
|
import * as ls from 'vscode-languageserver-types';
|
||||||
|
|
||||||
|
|
@ -19,7 +19,7 @@ import IDisposable = monaco.IDisposable;
|
||||||
|
|
||||||
|
|
||||||
export interface WorkerAccessor {
|
export interface WorkerAccessor {
|
||||||
(...more: Uri[]): Thenable<JSONWorker>
|
(...more: Uri[]): Thenable<YAMLWorker>
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- diagnostics --- ---
|
// --- diagnostics --- ---
|
||||||
|
|
@ -234,7 +234,7 @@ function toCompletionItem(entry: ls.CompletionItem): DataCompletionItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
function fromCompletionItem(entry: DataCompletionItem): ls.CompletionItem {
|
function fromCompletionItem(entry: DataCompletionItem): ls.CompletionItem {
|
||||||
let item : ls.CompletionItem = {
|
let item: ls.CompletionItem = {
|
||||||
label: entry.label,
|
label: entry.label,
|
||||||
sortText: entry.sortText,
|
sortText: entry.sortText,
|
||||||
filterText: entry.filterText,
|
filterText: entry.filterText,
|
||||||
|
|
@ -247,7 +247,7 @@ function fromCompletionItem(entry: DataCompletionItem): ls.CompletionItem {
|
||||||
item.insertText = entry.insertText.value;
|
item.insertText = entry.insertText.value;
|
||||||
item.insertTextFormat = ls.InsertTextFormat.Snippet
|
item.insertTextFormat = ls.InsertTextFormat.Snippet
|
||||||
} else {
|
} else {
|
||||||
item.insertText = <string> entry.insertText;
|
item.insertText = <string>entry.insertText;
|
||||||
}
|
}
|
||||||
if (entry.range) {
|
if (entry.range) {
|
||||||
item.textEdit = ls.TextEdit.replace(fromRange(entry.range), item.insertText);
|
item.textEdit = ls.TextEdit.replace(fromRange(entry.range), item.insertText);
|
||||||
|
|
@ -276,7 +276,7 @@ export class CompletionAdapter implements monaco.languages.CompletionItemProvide
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let items: monaco.languages.CompletionItem[] = info.items.map(entry => {
|
let items: monaco.languages.CompletionItem[] = info.items.map(entry => {
|
||||||
let item : monaco.languages.CompletionItem = {
|
let item: monaco.languages.CompletionItem = {
|
||||||
label: entry.label,
|
label: entry.label,
|
||||||
insertText: entry.insertText,
|
insertText: entry.insertText,
|
||||||
sortText: entry.sortText,
|
sortText: entry.sortText,
|
||||||
|
|
@ -290,7 +290,7 @@ export class CompletionAdapter implements monaco.languages.CompletionItemProvide
|
||||||
item.insertText = entry.textEdit.newText;
|
item.insertText = entry.textEdit.newText;
|
||||||
}
|
}
|
||||||
if (entry.insertTextFormat === ls.InsertTextFormat.Snippet) {
|
if (entry.insertTextFormat === ls.InsertTextFormat.Snippet) {
|
||||||
item.insertText = { value: <string> item.insertText };
|
item.insertText = { value: <string>item.insertText };
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
|
|
@ -403,7 +403,7 @@ export class DocumentSymbolAdapter implements monaco.languages.DocumentSymbolPro
|
||||||
function fromFormattingOptions(options: monaco.languages.FormattingOptions): ls.FormattingOptions {
|
function fromFormattingOptions(options: monaco.languages.FormattingOptions): ls.FormattingOptions {
|
||||||
return {
|
return {
|
||||||
tabSize: options.tabSize,
|
tabSize: options.tabSize,
|
||||||
insertSpaces: options.insertSpaces
|
insertSpaces: options.insertSpaces
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import * as mode from './jsonMode';
|
import * as mode from './yamlMode';
|
||||||
|
|
||||||
import Emitter = monaco.Emitter;
|
import Emitter = monaco.Emitter;
|
||||||
import IEvent = monaco.IEvent;
|
import IEvent = monaco.IEvent;
|
||||||
|
|
@ -14,18 +14,18 @@ declare var require: <T>(moduleId: [string], callback: (module: T) => void) => v
|
||||||
|
|
||||||
// --- JSON configuration and defaults ---------
|
// --- JSON configuration and defaults ---------
|
||||||
|
|
||||||
export class LanguageServiceDefaultsImpl implements monaco.languages.json.LanguageServiceDefaults {
|
export class LanguageServiceDefaultsImpl implements monaco.languages.yaml.LanguageServiceDefaults {
|
||||||
|
|
||||||
private _onDidChange = new Emitter<monaco.languages.json.LanguageServiceDefaults>();
|
private _onDidChange = new Emitter<monaco.languages.yaml.LanguageServiceDefaults>();
|
||||||
private _diagnosticsOptions: monaco.languages.json.DiagnosticsOptions;
|
private _diagnosticsOptions: monaco.languages.yaml.DiagnosticsOptions;
|
||||||
private _languageId: string;
|
private _languageId: string;
|
||||||
|
|
||||||
constructor(languageId: string, diagnosticsOptions: monaco.languages.json.DiagnosticsOptions) {
|
constructor(languageId: string, diagnosticsOptions: monaco.languages.yaml.DiagnosticsOptions) {
|
||||||
this._languageId = languageId;
|
this._languageId = languageId;
|
||||||
this.setDiagnosticsOptions(diagnosticsOptions);
|
this.setDiagnosticsOptions(diagnosticsOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
get onDidChange(): IEvent<monaco.languages.json.LanguageServiceDefaults> {
|
get onDidChange(): IEvent<monaco.languages.yaml.LanguageServiceDefaults> {
|
||||||
return this._onDidChange.event;
|
return this._onDidChange.event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,45 +33,42 @@ export class LanguageServiceDefaultsImpl implements monaco.languages.json.Langua
|
||||||
return this._languageId;
|
return this._languageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
get diagnosticsOptions(): monaco.languages.json.DiagnosticsOptions {
|
get diagnosticsOptions(): monaco.languages.yaml.DiagnosticsOptions {
|
||||||
return this._diagnosticsOptions;
|
return this._diagnosticsOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
setDiagnosticsOptions(options: monaco.languages.json.DiagnosticsOptions): void {
|
setDiagnosticsOptions(options: monaco.languages.yaml.DiagnosticsOptions): void {
|
||||||
this._diagnosticsOptions = options || Object.create(null);
|
this._diagnosticsOptions = options || Object.create(null);
|
||||||
this._onDidChange.fire(this);
|
this._onDidChange.fire(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const diagnosticDefault: monaco.languages.json.DiagnosticsOptions = {
|
const diagnosticDefault: monaco.languages.yaml.DiagnosticsOptions = {
|
||||||
validate: true,
|
validate: true,
|
||||||
allowComments: true,
|
|
||||||
schemas: []
|
schemas: []
|
||||||
}
|
}
|
||||||
|
|
||||||
const jsonDefaults = new LanguageServiceDefaultsImpl('json', diagnosticDefault);
|
const yamlDefaults = new LanguageServiceDefaultsImpl('yaml', diagnosticDefault);
|
||||||
|
|
||||||
|
|
||||||
// Export API
|
// Export API
|
||||||
function createAPI(): typeof monaco.languages.json {
|
function createAPI(): typeof monaco.languages.yaml {
|
||||||
return {
|
return {
|
||||||
jsonDefaults: jsonDefaults,
|
yamlDefaults: yamlDefaults,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
monaco.languages.json = createAPI();
|
monaco.languages.yaml = createAPI();
|
||||||
|
|
||||||
// --- Registration to monaco editor ---
|
// --- Registration to monaco editor ---
|
||||||
|
|
||||||
function withMode(callback: (module: typeof mode) => void): void {
|
function withMode(callback: (module: typeof mode) => void): void {
|
||||||
require<typeof mode>(['vs/language/json/jsonMode'], callback);
|
require<typeof mode>(['hl/yaml/yamlMode'], callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
monaco.languages.register({
|
// monaco.languages.register({
|
||||||
id: 'json',
|
// id: 'yaml',
|
||||||
extensions: ['.json', '.bowerrc', '.jshintrc', '.jscsrc', '.eslintrc', '.babelrc'],
|
// extensions: ['.yml'],
|
||||||
aliases: ['JSON', 'json'],
|
// });
|
||||||
mimetypes: ['application/json'],
|
monaco.languages.onLanguage('yaml', () => {
|
||||||
});
|
withMode(mode => mode.setupMode(yamlDefaults));
|
||||||
monaco.languages.onLanguage('json', () => {
|
|
||||||
withMode(mode => mode.setupMode(jsonDefaults));
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
8
src/monaco.d.ts
vendored
8
src/monaco.d.ts
vendored
|
|
@ -3,16 +3,12 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
declare module monaco.languages.json {
|
declare module monaco.languages.yaml {
|
||||||
export interface DiagnosticsOptions {
|
export interface DiagnosticsOptions {
|
||||||
/**
|
/**
|
||||||
* If set, the validator will be enabled and perform syntax validation as well as schema based validation.
|
* If set, the validator will be enabled and perform syntax validation as well as schema based validation.
|
||||||
*/
|
*/
|
||||||
readonly validate?: boolean;
|
readonly validate?: boolean;
|
||||||
/**
|
|
||||||
* If set, comments are tolerated. If set to false, syntax errors will be emmited for comments.
|
|
||||||
*/
|
|
||||||
readonly allowComments?: boolean;
|
|
||||||
/**
|
/**
|
||||||
* A list of known schemas and/or associations of schemas to file names.
|
* A list of known schemas and/or associations of schemas to file names.
|
||||||
*/
|
*/
|
||||||
|
|
@ -38,5 +34,5 @@ declare module monaco.languages.json {
|
||||||
setDiagnosticsOptions(options: DiagnosticsOptions): void;
|
setDiagnosticsOptions(options: DiagnosticsOptions): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export var jsonDefaults: LanguageServiceDefaults;
|
export var yamlDefaults: LanguageServiceDefaults;
|
||||||
}
|
}
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import {LanguageServiceDefaultsImpl} from './monaco.contribution';
|
import { LanguageServiceDefaultsImpl } from './monaco.contribution';
|
||||||
import {JSONWorker} from './jsonWorker';
|
import { YAMLWorker } from './yamlWorker';
|
||||||
|
|
||||||
import Promise = monaco.Promise;
|
import Promise = monaco.Promise;
|
||||||
import IDisposable = monaco.IDisposable;
|
import IDisposable = monaco.IDisposable;
|
||||||
|
|
@ -20,8 +20,8 @@ export class WorkerManager {
|
||||||
private _lastUsedTime: number;
|
private _lastUsedTime: number;
|
||||||
private _configChangeListener: IDisposable;
|
private _configChangeListener: IDisposable;
|
||||||
|
|
||||||
private _worker: monaco.editor.MonacoWebWorker<JSONWorker>;
|
private _worker: monaco.editor.MonacoWebWorker<YAMLWorker>;
|
||||||
private _client: Promise<JSONWorker>;
|
private _client: Promise<YAMLWorker>;
|
||||||
|
|
||||||
constructor(defaults: LanguageServiceDefaultsImpl) {
|
constructor(defaults: LanguageServiceDefaultsImpl) {
|
||||||
this._defaults = defaults;
|
this._defaults = defaults;
|
||||||
|
|
@ -55,14 +55,14 @@ export class WorkerManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getClient(): Promise<JSONWorker> {
|
private _getClient(): Promise<YAMLWorker> {
|
||||||
this._lastUsedTime = Date.now();
|
this._lastUsedTime = Date.now();
|
||||||
|
|
||||||
if (!this._client) {
|
if (!this._client) {
|
||||||
this._worker = monaco.editor.createWebWorker<JSONWorker>({
|
this._worker = monaco.editor.createWebWorker<YAMLWorker>({
|
||||||
|
|
||||||
// module that exports the create() method and returns a `JSONWorker` instance
|
// module that exports the create() method and returns a `YAMLWorker` instance
|
||||||
moduleId: 'vs/language/json/jsonWorker',
|
moduleId: 'hl/yaml/yamlWorker',
|
||||||
|
|
||||||
label: this._defaults.languageId,
|
label: this._defaults.languageId,
|
||||||
|
|
||||||
|
|
@ -79,8 +79,8 @@ export class WorkerManager {
|
||||||
return this._client;
|
return this._client;
|
||||||
}
|
}
|
||||||
|
|
||||||
getLanguageServiceWorker(...resources: Uri[]): Promise<JSONWorker> {
|
getLanguageServiceWorker(...resources: Uri[]): Promise<YAMLWorker> {
|
||||||
let _client: JSONWorker;
|
let _client: YAMLWorker;
|
||||||
return toShallowCancelPromise(
|
return toShallowCancelPromise(
|
||||||
this._getClient().then((client) => {
|
this._getClient().then((client) => {
|
||||||
_client = client
|
_client = client
|
||||||
|
|
|
||||||
|
|
@ -52,12 +52,12 @@ export class YAMLCompletion {
|
||||||
};
|
};
|
||||||
|
|
||||||
let offset = document.offsetAt(position);
|
let offset = document.offsetAt(position);
|
||||||
if(document.getText()[offset] === ":"){
|
if (document.getText()[offset] === ":") {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let currentDoc = matchOffsetToDocument(offset, doc);
|
let currentDoc = matchOffsetToDocument(offset, doc);
|
||||||
if(currentDoc === null){
|
if (currentDoc === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let node = currentDoc.getNodeFromOffsetEndInclusive(offset);
|
let node = currentDoc.getNodeFromOffsetEndInclusive(offset);
|
||||||
|
|
@ -94,7 +94,7 @@ export class YAMLCompletion {
|
||||||
|
|
||||||
return this.schemaService.getSchemaForResource(document.uri).then((schema) => {
|
return this.schemaService.getSchemaForResource(document.uri).then((schema) => {
|
||||||
|
|
||||||
if(!schema){
|
if (!schema) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,6 +176,7 @@ export class YAMLCompletion {
|
||||||
collector.add({
|
collector.add({
|
||||||
kind: CompletionItemKind.Property,
|
kind: CompletionItemKind.Property,
|
||||||
label: key,
|
label: key,
|
||||||
|
insertText: `${key}:`,
|
||||||
filterText: this.getFilterTextForValue(key),
|
filterText: this.getFilterTextForValue(key),
|
||||||
documentation: propertySchema.description || ''
|
documentation: propertySchema.description || ''
|
||||||
});
|
});
|
||||||
|
|
@ -197,17 +198,17 @@ export class YAMLCompletion {
|
||||||
node = node.parent;
|
node = node.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(node && node.type === 'null'){
|
if (node && node.type === 'null') {
|
||||||
let nodeParent = node.parent;
|
let nodeParent = node.parent;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is going to be an object for some reason and we need to find the property
|
* This is going to be an object for some reason and we need to find the property
|
||||||
* Its an issue with the null node
|
* Its an issue with the null node
|
||||||
*/
|
*/
|
||||||
if(nodeParent && nodeParent.type === "object"){
|
if (nodeParent && nodeParent.type === "object") {
|
||||||
for(let prop in nodeParent["properties"]){
|
for (let prop in nodeParent["properties"]) {
|
||||||
let currNode = nodeParent["properties"][prop];
|
let currNode = nodeParent["properties"][prop];
|
||||||
if(currNode.key && currNode.key.location === node.location){
|
if (currNode.key && currNode.key.location === node.location) {
|
||||||
node = currNode;
|
node = currNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -252,7 +253,7 @@ export class YAMLCompletion {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if(node){
|
if (node) {
|
||||||
if (types['boolean']) {
|
if (types['boolean']) {
|
||||||
this.addBooleanValueCompletion(true, collector);
|
this.addBooleanValueCompletion(true, collector);
|
||||||
this.addBooleanValueCompletion(false, collector);
|
this.addBooleanValueCompletion(false, collector);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import jsyaml = require('js-yaml')
|
import * as jsyaml from 'js-yaml'
|
||||||
import { EOL } from 'os';
|
import { EOL } from 'os';
|
||||||
import { TextDocument, Range, Position, FormattingOptions, TextEdit } from 'vscode-languageserver-types';
|
import { TextDocument, Range, Position, FormattingOptions, TextEdit } from 'vscode-languageserver-types';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import {WorkerManager} from './workerManager';
|
import { WorkerManager } from './workerManager';
|
||||||
import {JSONWorker} from './jsonWorker';
|
import { YAMLWorker } from './yamlWorker';
|
||||||
import {LanguageServiceDefaultsImpl} from './monaco.contribution';
|
import { LanguageServiceDefaultsImpl } from './monaco.contribution';
|
||||||
import * as languageFeatures from './languageFeatures';
|
import * as languageFeatures from './languageFeatures';
|
||||||
import {createTokenizationSupport} from './tokenization';
|
// import { createTokenizationSupport } from './tokenization';
|
||||||
|
|
||||||
import Promise = monaco.Promise;
|
import Promise = monaco.Promise;
|
||||||
import Uri = monaco.Uri;
|
import Uri = monaco.Uri;
|
||||||
|
|
@ -21,7 +21,7 @@ export function setupMode(defaults: LanguageServiceDefaultsImpl): void {
|
||||||
const client = new WorkerManager(defaults);
|
const client = new WorkerManager(defaults);
|
||||||
disposables.push(client);
|
disposables.push(client);
|
||||||
|
|
||||||
const worker: languageFeatures.WorkerAccessor = (...uris: Uri[]): Promise<JSONWorker> => {
|
const worker: languageFeatures.WorkerAccessor = (...uris: Uri[]): Promise<YAMLWorker> => {
|
||||||
return client.getLanguageServiceWorker(...uris);
|
return client.getLanguageServiceWorker(...uris);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -33,28 +33,40 @@ export function setupMode(defaults: LanguageServiceDefaultsImpl): void {
|
||||||
disposables.push(monaco.languages.registerDocumentFormattingEditProvider(languageId, new languageFeatures.DocumentFormattingEditProvider(worker)));
|
disposables.push(monaco.languages.registerDocumentFormattingEditProvider(languageId, new languageFeatures.DocumentFormattingEditProvider(worker)));
|
||||||
disposables.push(monaco.languages.registerDocumentRangeFormattingEditProvider(languageId, new languageFeatures.DocumentRangeFormattingEditProvider(worker)));
|
disposables.push(monaco.languages.registerDocumentRangeFormattingEditProvider(languageId, new languageFeatures.DocumentRangeFormattingEditProvider(worker)));
|
||||||
disposables.push(new languageFeatures.DiagnostcsAdapter(languageId, worker));
|
disposables.push(new languageFeatures.DiagnostcsAdapter(languageId, worker));
|
||||||
disposables.push(monaco.languages.setTokensProvider(languageId, createTokenizationSupport(true)));
|
// disposables.push(monaco.languages.setTokensProvider(languageId, createTokenizationSupport(true)));
|
||||||
disposables.push(monaco.languages.setLanguageConfiguration(languageId, richEditConfiguration));
|
disposables.push(monaco.languages.setLanguageConfiguration(languageId, richEditConfiguration));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const richEditConfiguration: monaco.languages.LanguageConfiguration = {
|
const richEditConfiguration: monaco.languages.LanguageConfiguration = {
|
||||||
wordPattern: /(-?\d*\.\d\w*)|([^\[\{\]\}\:\"\,\s]+)/g,
|
|
||||||
|
|
||||||
comments: {
|
comments: {
|
||||||
lineComment: '//',
|
lineComment: '#'
|
||||||
blockComment: ['/*', '*/']
|
|
||||||
},
|
},
|
||||||
|
|
||||||
brackets: [
|
brackets: [
|
||||||
['{', '}'],
|
['{', '}'],
|
||||||
['[', ']']
|
['[', ']'],
|
||||||
|
['(', ')']
|
||||||
|
],
|
||||||
|
autoClosingPairs: [
|
||||||
|
{ open: '{', close: '}' },
|
||||||
|
{ open: '[', close: ']' },
|
||||||
|
{ open: '(', close: ')' },
|
||||||
|
{ open: '"', close: '"' },
|
||||||
|
{ open: '\'', close: '\'' },
|
||||||
|
],
|
||||||
|
surroundingPairs: [
|
||||||
|
{ open: '{', close: '}' },
|
||||||
|
{ open: '[', close: ']' },
|
||||||
|
{ open: '(', close: ')' },
|
||||||
|
{ open: '"', close: '"' },
|
||||||
|
{ open: '\'', close: '\'' },
|
||||||
],
|
],
|
||||||
|
|
||||||
autoClosingPairs: [
|
onEnterRules: [
|
||||||
{ open: '{', close: '}', notIn: ['string'] },
|
{
|
||||||
{ open: '[', close: ']', notIn: ['string'] },
|
beforeText: /:\s*$/,
|
||||||
{ open: '"', close: '"', notIn: ['string'] }
|
action: { indentAction: monaco.languages.IndentAction.Indent }
|
||||||
]
|
}
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
146
src/yamlWorker.ts
Normal file
146
src/yamlWorker.ts
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Red Hat, Inc. All rights reserved.
|
||||||
|
* Copyright (c) Adam Voss. 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.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import Promise = monaco.Promise;
|
||||||
|
import Thenable = monaco.Thenable;
|
||||||
|
import IWorkerContext = monaco.worker.IWorkerContext;
|
||||||
|
|
||||||
|
import * as yamlService from './yaml-languageservice/yamlLanguageService';
|
||||||
|
import * as ls from 'vscode-languageserver-types';
|
||||||
|
import { getLineOffsets } from './yaml-languageservice/utils/arrUtils';
|
||||||
|
import { parse as parseYAML } from "./yaml-languageservice/parser/yamlParser";
|
||||||
|
|
||||||
|
export class YAMLWorker {
|
||||||
|
|
||||||
|
private _ctx: IWorkerContext;
|
||||||
|
private _languageService: yamlService.LanguageService;
|
||||||
|
private _languageSettings: yamlService.LanguageSettings;
|
||||||
|
private _languageId: string;
|
||||||
|
|
||||||
|
constructor(ctx: IWorkerContext, createData: ICreateData) {
|
||||||
|
this._ctx = ctx;
|
||||||
|
this._languageSettings = createData.languageSettings;
|
||||||
|
this._languageId = createData.languageId;
|
||||||
|
this._languageService = yamlService.getLanguageService();
|
||||||
|
this._languageService.configure(this._languageSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
doValidation(uri: string): Thenable<ls.Diagnostic[]> {
|
||||||
|
let document = this._getTextDocument(uri);
|
||||||
|
if (document) {
|
||||||
|
let jsonDocument = this._languageService.parseYAMLDocument(document);
|
||||||
|
return this._languageService.doValidation(document, jsonDocument);
|
||||||
|
}
|
||||||
|
return Promise.as([]);
|
||||||
|
}
|
||||||
|
doComplete(uri: string, position: ls.Position): Thenable<ls.CompletionList> {
|
||||||
|
let document = this._getTextDocument(uri);
|
||||||
|
let completionFix = completionHelper(document, position);
|
||||||
|
let newText = completionFix.newText;
|
||||||
|
let jsonDocument = parseYAML(newText);
|
||||||
|
return this._languageService.doComplete(document, position, jsonDocument);
|
||||||
|
}
|
||||||
|
doResolve(item: ls.CompletionItem): Thenable<ls.CompletionItem> {
|
||||||
|
return this._languageService.doResolve(item);
|
||||||
|
}
|
||||||
|
doHover(uri: string, position: ls.Position): Thenable<ls.Hover> {
|
||||||
|
let document = this._getTextDocument(uri);
|
||||||
|
let jsonDocument = this._languageService.parseYAMLDocument(document);
|
||||||
|
return this._languageService.doHover(document, position, jsonDocument);
|
||||||
|
}
|
||||||
|
format(uri: string, range: ls.Range, options: ls.FormattingOptions): Thenable<ls.TextEdit[]> {
|
||||||
|
let document = this._getTextDocument(uri);
|
||||||
|
let textEdits = this._languageService.format(document, options);
|
||||||
|
return Promise.as(textEdits);
|
||||||
|
}
|
||||||
|
resetSchema(uri: string): Thenable<boolean> {
|
||||||
|
return Promise.as(this._languageService.resetSchema(uri));
|
||||||
|
}
|
||||||
|
findDocumentSymbols(uri: string): Promise<ls.SymbolInformation[]> {
|
||||||
|
let document = this._getTextDocument(uri);
|
||||||
|
let jsonDocument = this._languageService.parseYAMLDocument(document);
|
||||||
|
let symbols = this._languageService.findDocumentSymbols(document, jsonDocument);
|
||||||
|
return Promise.as(symbols);
|
||||||
|
}
|
||||||
|
private _getTextDocument(uri: string): ls.TextDocument {
|
||||||
|
let models = this._ctx.getMirrorModels();
|
||||||
|
for (let model of models) {
|
||||||
|
if (model.uri.toString() === uri) {
|
||||||
|
return ls.TextDocument.create(uri, this._languageId, model.version, model.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICreateData {
|
||||||
|
languageId: string;
|
||||||
|
languageSettings: yamlService.LanguageSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function create(ctx: IWorkerContext, createData: ICreateData): YAMLWorker {
|
||||||
|
return new YAMLWorker(ctx, createData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// https://github.com/redhat-developer/yaml-language-server/blob/5e069c0e9d7004d57f1fa6e93df670d4895883d1/src/server.ts#L453
|
||||||
|
function completionHelper(document: ls.TextDocument, textDocumentPosition: ls.Position) {
|
||||||
|
|
||||||
|
//Get the string we are looking at via a substring
|
||||||
|
let linePos = textDocumentPosition.line;
|
||||||
|
let position = textDocumentPosition;
|
||||||
|
let lineOffset = getLineOffsets(document.getText());
|
||||||
|
let start = lineOffset[linePos]; //Start of where the autocompletion is happening
|
||||||
|
let end = 0; //End of where the autocompletion is happening
|
||||||
|
if (lineOffset[linePos + 1]) {
|
||||||
|
end = lineOffset[linePos + 1];
|
||||||
|
} else {
|
||||||
|
end = document.getText().length;
|
||||||
|
}
|
||||||
|
let textLine = document.getText().substring(start, end);
|
||||||
|
|
||||||
|
//Check if the string we are looking at is a node
|
||||||
|
if (textLine.indexOf(":") === -1) {
|
||||||
|
//We need to add the ":" to load the nodes
|
||||||
|
let newText = "";
|
||||||
|
|
||||||
|
//This is for the empty line case
|
||||||
|
let trimmedText = textLine.trim();
|
||||||
|
if (trimmedText.length === 0 || (trimmedText.length === 1 && trimmedText[0] === '-')) {
|
||||||
|
//Add a temp node that is in the document but we don't use at all.
|
||||||
|
if (lineOffset[linePos + 1]) {
|
||||||
|
newText = document.getText().substring(0, start + (textLine.length - 1)) + "holder:\r\n" + document.getText().substr(end + 2);
|
||||||
|
} else {
|
||||||
|
newText = document.getText().substring(0, start + (textLine.length)) + "holder:\r\n" + document.getText().substr(end + 2);
|
||||||
|
}
|
||||||
|
//For when missing semi colon case
|
||||||
|
} else {
|
||||||
|
//Add a semicolon to the end of the current line so we can validate the node
|
||||||
|
if (lineOffset[linePos + 1]) {
|
||||||
|
newText = document.getText().substring(0, start + (textLine.length - 1)) + ":\r\n" + document.getText().substr(end + 2);
|
||||||
|
} else {
|
||||||
|
newText = document.getText().substring(0, start + (textLine.length)) + ":\r\n" + document.getText().substr(end + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"newText": newText,
|
||||||
|
"newPosition": textDocumentPosition
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
//All the nodes are loaded
|
||||||
|
position.character = position.character - 1;
|
||||||
|
return {
|
||||||
|
"newText": document.getText(),
|
||||||
|
"newPosition": position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue