UNPKG

monaco-sql-languages

Version:

SQL languages for the Monaco Editor, based on monaco-languages.

260 lines (259 loc) 11.4 kB
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; }); } }