@krassowski/jupyterlab-lsp
Version:
Language Server Protocol integration for JupyterLab
287 lines • 9.74 kB
JavaScript
import { CodeMirrorEditor, CodeMirrorEditorFactory, CodeMirrorMimeTypeService } from '@jupyterlab/codemirror';
import { Context, TextModelFactory } from '@jupyterlab/docregistry';
import { FileEditorFactory } from '@jupyterlab/fileeditor';
import { NotebookModel, NotebookModelFactory } from '@jupyterlab/notebook';
import { ServiceManager } from '@jupyterlab/services';
import { Mock, NBTestUtils } from '@jupyterlab/testutils';
import { Signal } from '@lumino/signaling';
import { FileEditorAdapter } from '../adapters/file_editor/file_editor';
import { NotebookAdapter } from '../adapters/notebook/notebook';
import { LSPConnection } from '../connection';
import { DocumentConnectionManager } from '../connection_manager';
import { FeatureManager } from '../index';
import { LanguageServerManager } from '../manager';
import { CodeMirrorVirtualEditor } from '../virtual/codemirror_editor';
import { BrowserConsole } from '../virtual/console';
import { VirtualDocument } from '../virtual/document';
import { VirtualEditorManager } from '../virtual/editor';
var createNotebookPanel = NBTestUtils.createNotebookPanel;
const DEFAULT_SERVER_ID = 'pylsp';
export class MockLanguageServerManager extends LanguageServerManager {
async fetchSessions() {
this._sessions = new Map();
this._sessions.set(DEFAULT_SERVER_ID, {
spec: {
languages: ['python']
}
});
this._sessionsChanged.emit(void 0);
}
}
export class MockSettings {
constructor(settings) {
this.settings = settings;
this.changed = new Signal(this);
}
get composite() {
return this.settings;
}
set(setting, value) {
this.settings[setting] = value;
}
}
export class MockExtension {
constructor() {
this.app = null;
this.feature_manager = new FeatureManager();
this.editor_type_manager = new VirtualEditorManager();
this.language_server_manager = new MockLanguageServerManager({
console: new BrowserConsole()
});
this.connection_manager = new DocumentConnectionManager({
language_server_manager: this.language_server_manager,
console: new BrowserConsole()
});
this.editor_type_manager.registerEditorType({
implementation: CodeMirrorVirtualEditor,
name: 'CodeMirrorEditor',
supports: CodeMirrorEditor
});
this.foreign_code_extractors = {};
this.code_overrides = {};
this.console = new BrowserConsole();
this.user_console = null;
}
}
export class TestEnvironment {
constructor(options) {
this.document_options = Object.assign(Object.assign({}, this.get_defaults()), (options || {}));
this.extension = new MockExtension();
this.init();
}
init() {
this.widget = this.create_widget();
let adapter_type = this.get_adapter_type();
this.adapter = new adapter_type(this.extension, this.widget);
this.virtual_editor = this.create_virtual_editor();
// override the virtual editor with a mock/test one
this.adapter.virtual_editor = this.virtual_editor;
this.adapter.initialized
.then(() => {
// override it again after initialization
// TODO: rewrite tests to async to only override after initialization
this.adapter.virtual_editor = this.virtual_editor;
})
.catch(console.error);
}
create_virtual_editor() {
return new CodeMirrorVirtualEditor({
adapter: this.adapter,
virtual_document: new VirtualDocument(this.document_options)
});
}
dispose() {
this.adapter.dispose();
}
}
function FeatureSupport(Base) {
return class FeatureTestEnvironment extends Base {
init() {
this._connections = new Map();
super.init();
}
get status_message() {
return this.adapter.status_message;
}
init_integration(options) {
let connection = this.create_dummy_connection();
let document = options.document
? options.document
: this.virtual_editor.virtual_document;
let editor_adapter = this.adapter.connect_adapter(document, connection, [
{
id: options.id,
name: options.id,
editorIntegrationFactory: new Map([
['CodeMirrorEditor', options.constructor]
]),
settings: options.settings
}
]);
this.virtual_editor.virtual_document = document;
document.changed.connect(async () => {
await editor_adapter.updateAfterChange();
});
let feature = editor_adapter.features.get(options.id);
this._connections.set(feature, connection);
return feature;
}
dispose_feature(feature) {
let connection = this._connections.get(feature);
connection.close();
feature.is_registered = false;
}
create_dummy_connection() {
return new LSPConnection({
languageId: this.document_options.language,
serverUri: 'ws://localhost:8080',
rootUri: 'file:///unit-test',
serverIdentifier: DEFAULT_SERVER_ID,
console: new BrowserConsole(),
capabilities: {}
});
}
dispose() {
super.dispose();
for (let connection of this._connections.values()) {
connection.close();
}
}
};
}
export class FileEditorTestEnvironment extends TestEnvironment {
get_adapter_type() {
return FileEditorAdapter;
}
get_defaults() {
return {
language: 'python',
path: 'dummy.py',
file_extension: 'py',
has_lsp_supported_file: true,
standalone: true,
foreign_code_extractors: {},
overrides_registry: {},
console: new BrowserConsole()
};
}
get ce_editor() {
return this.widget.content.editor;
}
create_widget() {
let factory = new FileEditorFactory({
editorServices: {
factoryService: new CodeMirrorEditorFactory(),
mimeTypeService: new CodeMirrorMimeTypeService()
},
factoryOptions: {
name: 'Editor',
fileTypes: ['*']
}
});
const context = new Context({
manager: new Mock.ServiceManagerMock(),
factory: new TextModelFactory(),
path: this.document_options.path
});
return factory.createNew(context);
}
dispose() {
super.dispose();
this.ce_editor.dispose();
}
}
export class NotebookTestEnvironment extends TestEnvironment {
get_adapter_type() {
return NotebookAdapter;
}
get notebook() {
return this.widget.content;
}
get_defaults() {
return {
language: 'python',
path: 'notebook.ipynb',
file_extension: 'py',
overrides_registry: {},
foreign_code_extractors: {},
has_lsp_supported_file: false,
standalone: true,
console: new BrowserConsole()
};
}
create_widget() {
let context = new Context({
manager: new ServiceManager({ standby: 'never' }),
factory: new NotebookModelFactory({}),
path: this.document_options.path
});
return createNotebookPanel(context);
}
}
export class FileEditorFeatureTestEnvironment extends FeatureSupport(FileEditorTestEnvironment) {
}
export class NotebookFeatureTestEnvironment extends FeatureSupport(NotebookTestEnvironment) {
}
export function code_cell(source, metadata = { trusted: false }) {
return {
cell_type: 'code',
source: source,
metadata: metadata,
execution_count: null,
outputs: []
};
}
export function set_notebook_content(notebook, cells, metadata = python_notebook_metadata) {
let test_notebook = {
cells: cells,
metadata: metadata
};
notebook.model = new NotebookModel();
notebook.model.fromJSON(test_notebook);
}
export const python_notebook_metadata = {
kernelspec: {
display_name: 'Python [default]',
language: 'python',
name: 'python3'
},
language_info: {
codemirror_mode: {
name: 'ipython',
version: 3
},
file_extension: '.py',
mimetype: 'text/x-python',
name: 'python',
nbconvert_exporter: 'python',
pygments_lexer: 'ipython3',
version: '3.5.2'
},
orig_nbformat: 4.1
};
export function showAllCells(notebook) {
notebook.show();
// iterate over every cell to activate the editors
for (let i = 0; i < notebook.model.cells.length; i++) {
notebook.activeCellIndex = i;
notebook.activeCell.show();
}
}
export function getCellsJSON(notebook) {
let cells = [];
for (let i = 0; i < notebook.model.cells.length; i++) {
cells.push(notebook.model.cells.get(i));
}
return cells.map(cell => cell.toJSON());
}
export async function synchronize_content(environment, adapter) {
await environment.adapter.update_documents();
try {
await adapter.updateAfterChange();
}
catch (e) {
console.warn(e);
}
}
//# sourceMappingURL=testutils.js.map