monaco-sql-languages
Version:
SQL languages for the Monaco Editor, based on monaco-languages.
260 lines (259 loc) • 11.4 kB
JavaScript
import * as monaco from 'monaco-editor';
import { debounce } from './common/utils';
import { editor, MarkerSeverity, Range } from './fillers/monaco-editor-core';
export class DiagnosticsAdapter {
constructor(_languageId, _worker, _defaults) {
this._languageId = _languageId;
this._worker = _worker;
this._defaults = _defaults;
this._disposables = [];
this._listener = Object.create(null);
const onModelAdd = (model) => {
let modeId = model.getLanguageId();
if (modeId !== this._languageId) {
return;
}
this._listener[model.uri.toString()] = model.onDidChangeContent(debounce(() => {
this._doValidate(model.uri, modeId);
}, 500));
this._doValidate(model.uri, modeId);
};
const onModelRemoved = (model) => {
editor.setModelMarkers(model, this._languageId, []);
let uriStr = model.uri.toString();
let listener = this._listener[uriStr];
if (listener) {
listener.dispose();
delete this._listener[uriStr];
}
};
this._disposables.push(editor.onDidCreateModel(onModelAdd));
this._disposables.push(editor.onWillDisposeModel(onModelRemoved));
this._disposables.push(editor.onDidChangeModelLanguage((event) => {
onModelRemoved(event.model);
onModelAdd(event.model);
}));
this._disposables.push(this._defaults.onDidChange((_) => {
editor.getModels().forEach((model) => {
if (model.getLanguageId() === this._languageId) {
onModelRemoved(model);
onModelAdd(model);
}
});
}));
this._disposables.push({
dispose: () => {
for (let key in this._listener) {
this._listener[key].dispose();
}
}
});
editor.getModels().forEach(onModelAdd);
}
dispose() {
this._disposables.forEach((d) => d && d.dispose());
this._disposables = [];
}
_doValidate(resource, languageId) {
this._worker(resource)
.then((worker) => {
var _a;
let code = ((_a = editor.getModel(resource)) === null || _a === void 0 ? void 0 : _a.getValue()) || '';
if (typeof this._defaults.preprocessCode === 'function') {
code = this._defaults.preprocessCode(code);
}
return worker.doValidation(code);
})
.then((diagnostics) => {
const markers = diagnostics.map((d) => toDiagnostics(resource, d));
let model = editor.getModel(resource);
if (model && model.getLanguageId() === languageId) {
editor.setModelMarkers(model, languageId, markers);
}
})
.then(undefined, (err) => {
console.error(err);
});
}
}
function toSeverity(lsSeverity) {
switch (lsSeverity) {
default:
return MarkerSeverity.Error;
}
}
function toDiagnostics(_resource, diag) {
return {
severity: toSeverity(),
startLineNumber: diag.startLine,
startColumn: diag.startColumn,
endLineNumber: diag.endLine,
endColumn: diag.endColumn,
message: diag.message,
code: undefined, // TODO: set error type
source: 'dt-sql-parser'
};
}
export class CompletionAdapter {
constructor(_worker, _defaults) {
this._worker = _worker;
this._defaults = _defaults;
}
get triggerCharacters() {
return Array.isArray(this._defaults.triggerCharacters)
? this._defaults.triggerCharacters
: ['.', ' '];
}
provideCompletionItems(model, position, context, _token) {
const resource = model.uri;
return this._worker(resource)
.then((worker) => {
var _a;
let code = ((_a = editor.getModel(resource)) === null || _a === void 0 ? void 0 : _a.getValue()) || '';
if (typeof this._defaults.preprocessCode === 'function') {
code = this._defaults.preprocessCode(code);
}
return worker.doCompletionWithEntities(code, position);
})
.then(({ suggestions, allEntities, context: semanticContext }) => {
let snippets = [];
if (semanticContext === null || semanticContext === void 0 ? void 0 : semanticContext.isStatementBeginning) {
snippets = this._defaults.completionSnippets.map((item) => (Object.assign(Object.assign({}, item), { insertText: typeof item.body === 'string' ? item.body : item.body.join('\n') })));
}
return this._defaults.completionService(model, position, context, suggestions, allEntities, snippets);
})
.then((completions) => {
const wordInfo = model.getWordUntilPosition(position);
const wordRange = new Range(position.lineNumber, wordInfo.startColumn, position.lineNumber, wordInfo.endColumn);
const unwrappedCompletions = Array.isArray(completions)
? completions
: completions.suggestions;
const completionItems = unwrappedCompletions.map((item) => {
var _a, _b;
return (Object.assign(Object.assign({}, item), { insertText: (_a = item.insertText) !== null && _a !== void 0 ? _a : (typeof item.label === 'string' ? item.label : item.label.label), range: (_b = item.range) !== null && _b !== void 0 ? _b : wordRange }));
});
return {
suggestions: completionItems,
dispose: Array.isArray(completions) ? undefined : completions.dispose,
incomplete: Array.isArray(completions) ? undefined : completions.incomplete
};
});
}
}
/**
* The adapter is for the definition of the symbol at the given position and document.
**/
export class DefinitionAdapter {
constructor(_worker, _defaults) {
this._worker = _worker;
this._defaults = _defaults;
}
/**
* Provide the definition of the symbol at the given position and document.
**/
provideDefinition(model, position, _token) {
const resource = model.uri;
const lineContent = model.getLineContent(position.lineNumber);
if (lineContent.startsWith('--'))
return null;
return this._worker(resource)
.then((worker) => {
let code = (model === null || model === void 0 ? void 0 : model.getValue()) || '';
if (typeof this._defaults.preprocessCode === 'function') {
code = this._defaults.preprocessCode(code);
}
return worker.getAllEntities(code);
})
.then((entities) => {
const word = model.getWordAtPosition(position);
let pos = {
line: -1,
startIndex: -1,
endIndex: -1,
startColumn: -1,
endColumn: -1
};
const curEntity = entities === null || entities === void 0 ? void 0 : entities.find((entity) => {
const entityPosition = entity.position;
if (entityPosition.startColumn === (word === null || word === void 0 ? void 0 : word.startColumn) &&
entityPosition.endColumn === (word === null || word === void 0 ? void 0 : word.endColumn) &&
entityPosition.line === position.lineNumber) {
return entity;
}
return null;
});
if (curEntity) {
for (let k in entities) {
const entity = entities[Number(k)];
if (entity.entityContextType.includes('Create') &&
(word === null || word === void 0 ? void 0 : word.word) &&
entity.text === (word === null || word === void 0 ? void 0 : word.word) &&
entity.entityContextType.includes(curEntity.entityContextType)) {
pos = entity.position;
break;
}
}
}
if (pos && pos.line !== -1) {
return {
uri: model.uri,
range: new monaco.Range(pos === null || pos === void 0 ? void 0 : pos.line, pos === null || pos === void 0 ? void 0 : pos.startColumn, pos === null || pos === void 0 ? void 0 : pos.line, pos === null || pos === void 0 ? void 0 : pos.endColumn)
};
}
});
}
}
/**
* The adapter is for the references of the symbol at the given position and document.
**/
export class ReferenceAdapter {
constructor(_worker, _defaults) {
this._worker = _worker;
this._defaults = _defaults;
}
/**
* Provide a set of project-wide references for the given position and document.
**/
provideReferences(model, position, _context, _token) {
const resource = model.uri;
const lineContent = model.getLineContent(position.lineNumber);
if (!lineContent.startsWith('CREATE'))
return;
return this._worker(resource)
.then((worker) => {
let code = (model === null || model === void 0 ? void 0 : model.getValue()) || '';
if (typeof this._defaults.preprocessCode === 'function') {
code = this._defaults.preprocessCode(code);
}
return worker.getAllEntities(model === null || model === void 0 ? void 0 : model.getValue());
})
.then((entities) => {
const word = model.getWordAtPosition(position);
const arr = [];
const curEntity = entities === null || entities === void 0 ? void 0 : entities.find((entity) => {
const entityPosition = entity.position;
if (entityPosition.startColumn === (word === null || word === void 0 ? void 0 : word.startColumn) &&
entityPosition.endColumn === (word === null || word === void 0 ? void 0 : word.endColumn) &&
entityPosition.line === position.lineNumber) {
return entity;
}
return null;
});
if (curEntity) {
entities === null || entities === void 0 ? void 0 : entities.forEach((entity) => {
if ((word === null || word === void 0 ? void 0 : word.word) &&
entity.text === (word === null || word === void 0 ? void 0 : word.word) &&
curEntity.entityContextType.includes(entity.entityContextType)) {
let pos = null;
pos = entity.position;
arr.push({
uri: model.uri,
range: new monaco.Range(pos === null || pos === void 0 ? void 0 : pos.line, pos === null || pos === void 0 ? void 0 : pos.startColumn, pos === null || pos === void 0 ? void 0 : pos.line, pos === null || pos === void 0 ? void 0 : pos.endColumn)
});
}
});
}
return arr;
});
}
}