coc.nvim
Version:
LSP based intellisense engine for neovim & vim8.
855 lines • 33.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const debounce_1 = require("debounce");
const fast_diff_1 = tslib_1.__importDefault(require("fast-diff"));
const fs_1 = tslib_1.__importDefault(require("fs"));
const isuri_1 = tslib_1.__importDefault(require("isuri"));
const path_1 = tslib_1.__importDefault(require("path"));
const rimraf_1 = tslib_1.__importDefault(require("rimraf"));
const semver_1 = tslib_1.__importDefault(require("semver"));
const util_1 = tslib_1.__importStar(require("util"));
const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol");
const vscode_uri_1 = require("vscode-uri");
const which_1 = tslib_1.__importDefault(require("which"));
const commands_1 = tslib_1.__importDefault(require("./commands"));
const events_1 = tslib_1.__importDefault(require("./events"));
const db_1 = tslib_1.__importDefault(require("./model/db"));
const extension_1 = tslib_1.__importDefault(require("./model/extension"));
const memos_1 = tslib_1.__importDefault(require("./model/memos"));
const util_2 = require("./util");
const mkdirp_1 = tslib_1.__importDefault(require("mkdirp"));
const array_1 = require("./util/array");
require("./util/extensions");
const factory_1 = require("./util/factory");
const fs_2 = require("./util/fs");
const watchman_1 = tslib_1.__importDefault(require("./watchman"));
const workspace_1 = tslib_1.__importDefault(require("./workspace"));
const createLogger = require('./util/logger');
const logger = createLogger('extensions');
function loadJson(file) {
try {
let content = fs_1.default.readFileSync(file, 'utf8');
return JSON.parse(content);
}
catch (e) {
return null;
}
}
class Extensions {
constructor() {
this.list = [];
this.disabled = new Set();
this._onDidLoadExtension = new vscode_languageserver_protocol_1.Emitter();
this._onDidActiveExtension = new vscode_languageserver_protocol_1.Emitter();
this._onDidUnloadExtension = new vscode_languageserver_protocol_1.Emitter();
this._additionalSchemes = {};
this.activated = false;
this.ready = true;
this.onDidLoadExtension = this._onDidLoadExtension.event;
this.onDidActiveExtension = this._onDidActiveExtension.event;
this.onDidUnloadExtension = this._onDidUnloadExtension.event;
}
async init(nvim) {
if (global.hasOwnProperty('__TEST__')) {
this.root = path_1.default.join(__dirname, './__tests__/extensions');
this.manager = new extension_1.default(this.root);
let filepath = path_1.default.join(this.root, 'db.json');
let db = this.db = new db_1.default(filepath);
}
else {
await this.initializeRoot();
}
let data = loadJson(this.db.filepath) || {};
let keys = Object.keys(data.extension || {});
for (let key of keys) {
if (data.extension[key].disabled == true) {
this.disabled.add(key);
}
}
if (process.env.COC_NO_PLUGINS)
return;
let stats = await this.globalExtensionStats();
let localStats = await this.localExtensionStats(stats);
stats = stats.concat(localStats);
this.memos = new memos_1.default(path_1.default.resolve(this.root, '../memos.json'));
await this.loadFileExtensions();
await Promise.all(stats.map(stat => {
return this.loadExtension(stat.root, stat.isLocal).catch(e => {
workspace_1.default.showMessage(`Can't load extension from ${stat.root}: ${e.message}'`, 'error');
});
}));
// watch for new local extension
workspace_1.default.watchOption('runtimepath', async (oldValue, newValue) => {
let result = fast_diff_1.default(oldValue, newValue);
for (let [changeType, value] of result) {
if (changeType == 1) {
let paths = value.replace(/,$/, '').split(',');
for (let p of paths) {
await this.loadExtension(p, true);
}
}
}
});
commands_1.default.register({
id: 'extensions.forceUpdateAll',
execute: async () => {
await this.cleanExtensions();
await this.installExtensions([]);
}
});
}
async activateExtensions() {
this.activated = true;
if (global.hasOwnProperty('__TEST__'))
return;
for (let item of this.list) {
let { id, packageJSON } = item.extension;
this.setupActiveEvents(id, packageJSON);
}
// check extensions need watch & install
this.checkExtensions().logError();
let config = workspace_1.default.getConfiguration('coc.preferences');
let interval = config.get('extensionUpdateCheck', 'daily');
if (interval != 'never') {
let now = new Date();
let day = new Date(now.getFullYear(), now.getMonth(), now.getDate() - (interval == 'daily' ? 0 : 7));
let ts = this.db.fetch('lastUpdate');
if (ts && Number(ts) > day.getTime())
return;
this.updateExtensions().logError();
}
}
async updateExtensions() {
if (!this.root)
await this.initializeRoot();
if (!this.npm)
return;
let lockedList = await this.getLockedList();
let stats = await this.globalExtensionStats();
let versionInfo = {};
stats = stats.filter(o => !this.disabled.has(o.id) && !lockedList.includes(o.id));
let names = stats.map(o => o.id);
let statusItem = workspace_1.default.createStatusBarItem(0, { progress: true });
statusItem.text = `Updating extensions.`;
statusItem.show();
await Promise.all(names.map(name => {
let o = stats.find(o => o.id == name);
return this.manager.update(this.npm, name, o.exotic ? o.uri : undefined).then(updated => {
if (updated)
this.reloadExtension(name).logError();
}, err => {
workspace_1.default.showMessage(`Error on update ${name}: ${err}`);
});
}));
this.db.push('lastUpdate', Date.now());
workspace_1.default.showMessage('Update completed', 'more');
statusItem.dispose();
}
async checkExtensions() {
let { globalExtensions, watchExtensions } = workspace_1.default.env;
if (globalExtensions && globalExtensions.length) {
let names = globalExtensions.filter(name => !this.isDisabled(name));
let folder = path_1.default.join(this.root, 'node_modules');
if (fs_1.default.existsSync(folder)) {
let files = await util_1.default.promisify(fs_1.default.readdir)(folder);
names = names.filter(s => files.indexOf(s) == -1);
}
let json = this.loadJson();
if (json && json.dependencies) {
let vals = Object.values(json.dependencies);
names = names.filter(s => vals.findIndex(val => val.indexOf(s) !== -1) == -1);
}
this.installExtensions(names).logError();
}
// watch for changes
if (watchExtensions && watchExtensions.length) {
let watchmanPath = workspace_1.default.getWatchmanPath();
if (!watchmanPath)
return;
let stats = await this.getExtensionStates();
for (let name of watchExtensions) {
let stat = stats.find(s => s.id == name);
if (stat && stat.state !== 'disabled') {
let directory = await util_1.default.promisify(fs_1.default.realpath)(stat.root);
let client = await watchman_1.default.createClient(watchmanPath, directory);
client.subscribe('**/*.js', debounce_1.debounce(async () => {
await this.reloadExtension(name);
workspace_1.default.showMessage(`reloaded ${name}`);
}, 100)).catch(_e => {
// noop
});
}
}
}
}
/**
* Install extensions, can be called without initialize.
*/
async installExtensions(list = []) {
let { npm } = this;
if (!npm)
return;
if (!this.root)
await this.initializeRoot();
let missing = this.getMissingExtensions();
if (missing.length)
list.push(...missing);
if (!list.length)
return;
list = array_1.distinct(list);
let statusItem = workspace_1.default.createStatusBarItem(0, { progress: true });
statusItem.show();
statusItem.text = `Installing ${list.join(' ')}`;
await Promise.all(list.map(def => {
return this.manager.install(npm, def).then(name => {
if (name)
this.onExtensionInstall(name).logError();
}, err => {
workspace_1.default.showMessage(`Error on install ${def}: ${err}`);
});
}));
statusItem.dispose();
}
/**
* Get list of extensions in package.json that not installed
*/
getMissingExtensions() {
let json = this.loadJson() || { dependencies: {} };
let ids = [];
for (let key of Object.keys(json.dependencies)) {
let folder = path_1.default.join(this.root, 'node_modules', key);
if (!fs_1.default.existsSync(folder)) {
let val = json.dependencies[key];
if (val.startsWith('http')) {
ids.push(val);
}
else {
ids.push(key);
}
}
}
return ids;
}
get npm() {
let npm = workspace_1.default.getConfiguration('npm').get('binPath', 'npm');
for (let exe of [npm, 'yarnpkg', 'yarn', 'npm']) {
try {
let res = which_1.default.sync(exe);
return res;
}
catch (e) {
continue;
}
}
workspace_1.default.showMessage(`Can't find npm or yarn in your $PATH`, 'error');
return null;
}
/**
* Get all loaded extensions.
*/
get all() {
return this.list.map(o => o.extension);
}
getExtension(id) {
return this.list.find(o => o.id == id);
}
getExtensionState(id) {
let disabled = this.isDisabled(id);
if (disabled)
return 'disabled';
let item = this.list.find(o => o.id == id);
if (!item)
return 'unknown';
let { extension } = item;
return extension.isActive ? 'activated' : 'loaded';
}
async getExtensionStates() {
let globalStats = await this.globalExtensionStats();
let localStats = await this.localExtensionStats(globalStats);
return globalStats.concat(localStats);
}
async getLockedList() {
let obj = await this.db.fetch('extension');
obj = obj || {};
return Object.keys(obj).filter(id => {
return obj[id].locked === true;
});
}
async toggleLock(id) {
let key = `extension.${id}.locked`;
let locked = await this.db.fetch(key);
if (locked) {
this.db.delete(key);
}
else {
this.db.push(key, true);
}
}
async toggleExtension(id) {
let state = this.getExtensionState(id);
if (state == null)
return;
if (state == 'activated') {
this.deactivate(id);
}
let key = `extension.${id}.disabled`;
this.db.push(key, state == 'disabled' ? false : true);
if (state != 'disabled') {
this.disabled.add(id);
// unload
let idx = this.list.findIndex(o => o.id == id);
this.list.splice(idx, 1);
}
else {
this.disabled.delete(id);
let p = global.hasOwnProperty('__TEST__') ? '' : 'node_modules';
let folder = path_1.default.join(this.root, p, id);
try {
await this.loadExtension(folder);
}
catch (e) {
workspace_1.default.showMessage(`Can't load extension ${id}: ${e.message}'`, 'error');
}
}
await util_2.wait(200);
}
async reloadExtension(id) {
let idx = this.list.findIndex(o => o.id == id);
let directory = idx == -1 ? null : this.list[idx].directory;
this.deactivate(id);
if (idx != -1)
this.list.splice(idx, 1);
await util_2.wait(200);
if (directory) {
await this.loadExtension(directory);
}
else {
this.activate(id);
}
}
/**
* Remove all installed extensions
*/
async cleanExtensions() {
let dir = path_1.default.join(this.root, 'node_modules');
if (!fs_1.default.existsSync(dir))
return;
let names = fs_1.default.readdirSync(dir);
for (let name of names) {
let file = path_1.default.join(dir, name);
let stat = await util_1.promisify(fs_1.default.lstat)(file);
if (stat.isSymbolicLink())
continue;
await util_1.promisify(rimraf_1.default)(file, { glob: false });
}
}
async uninstallExtension(ids) {
if (!ids.length)
return;
let status = workspace_1.default.createStatusBarItem(99, { progress: true });
try {
status.text = `Uninstalling ${ids.join(' ')}`;
status.show();
let removed = [];
for (let id of ids) {
if (!this.isGlobalExtension(id)) {
workspace_1.default.showMessage(`Global extension '${id}' not found.`, 'error');
continue;
}
this.deactivate(id);
removed.push(id);
}
for (let id of removed) {
let idx = this.list.findIndex(o => o.id == id);
if (idx != -1) {
this.list.splice(idx, 1);
this._onDidUnloadExtension.fire(id);
}
}
let json = this.loadJson() || { dependencies: {} };
for (let id of removed) {
delete json.dependencies[id];
let folder = path_1.default.join(this.root, 'node_modules', id);
if (fs_1.default.existsSync(folder)) {
await util_1.default.promisify(rimraf_1.default)(`${folder}`, { glob: false });
}
}
let jsonFile = path_1.default.join(this.root, 'package.json');
status.dispose();
fs_1.default.writeFileSync(jsonFile, JSON.stringify(json, null, 2), { encoding: 'utf8' });
workspace_1.default.showMessage(`Removed: ${ids.join(' ')}`);
}
catch (e) {
status.dispose();
workspace_1.default.showMessage(`Uninstall failed: ${e.message}`, 'error');
}
}
isDisabled(id) {
return this.disabled.has(id);
}
async onExtensionInstall(id) {
if (!id)
return;
let item = this.list.find(o => o.id == id);
if (item)
item.deactivate();
let folder = path_1.default.join(this.root, 'node_modules', id);
let stat = await fs_2.statAsync(folder);
if (stat && stat.isDirectory()) {
let jsonFile = path_1.default.join(folder, 'package.json');
let content = await fs_2.readFile(jsonFile, 'utf8');
let packageJSON = JSON.parse(content);
let { engines } = packageJSON;
if (!engines || (!engines.hasOwnProperty('coc') && !engines.hasOwnProperty('vscode')))
return;
await this.loadExtension(folder);
}
}
has(id) {
return this.list.find(o => o.id == id) != null;
}
isActivted(id) {
let item = this.list.find(o => o.id == id);
if (item && item.extension.isActive) {
return true;
}
return false;
}
async loadExtension(folder, isLocal = false) {
let jsonFile = path_1.default.join(folder, 'package.json');
let stat = await fs_2.statAsync(jsonFile);
if (!stat || !stat.isFile())
return;
let content = await fs_2.readFile(jsonFile, 'utf8');
let packageJSON = JSON.parse(content);
if (this.isDisabled(packageJSON.name))
return;
if (this.isActivted(packageJSON.name)) {
workspace_1.default.showMessage(`deactivate ${packageJSON.name}`);
this.deactivate(packageJSON.name);
await util_2.wait(200);
}
let { engines } = packageJSON;
if (engines && engines.hasOwnProperty('coc')) {
let required = engines.coc.replace(/^\^/, '>=');
if (!semver_1.default.satisfies(workspace_1.default.version, required)) {
workspace_1.default.showMessage(`Please update coc.nvim, ${packageJSON.name} requires coc.nvim ${engines.coc}`, 'warning');
}
this.createExtension(folder, Object.freeze(packageJSON), isLocal);
}
else if (engines && engines.hasOwnProperty('vscode')) {
this.createExtension(folder, Object.freeze(packageJSON), isLocal);
}
else {
logger.info(`engine coc & vscode not found in ${jsonFile}`);
}
}
async loadFileExtensions() {
if (!process.env.VIMCONFIG)
return;
let folder = path_1.default.join(process.env.VIMCONFIG, 'coc-extensions');
if (!fs_1.default.existsSync(folder))
return;
let files = await fs_2.readdirAsync(folder);
files = files.filter(f => f.endsWith('.js'));
for (let file of files) {
this.loadExtensionFile(path_1.default.join(folder, file));
}
}
/**
* Load single javascript file as extension.
*/
loadExtensionFile(filepath) {
let filename = path_1.default.basename(filepath);
let name = path_1.default.basename(filepath, 'js');
if (this.isDisabled(name))
return;
let root = path_1.default.dirname(filepath);
let packageJSON = {
name,
main: filename,
};
this.createExtension(root, packageJSON);
}
activate(id, silent = true) {
if (this.isDisabled(id)) {
if (!silent)
workspace_1.default.showMessage(`Extension ${id} is disabled!`, 'error');
return;
}
let item = this.list.find(o => o.id == id);
if (!item) {
workspace_1.default.showMessage(`Extension ${id} not found!`, 'error');
return;
}
let { extension } = item;
if (extension.isActive)
return;
extension.activate().then(() => {
if (extension.isActive) {
this._onDidActiveExtension.fire(extension);
}
}, e => {
workspace_1.default.showMessage(`Error on activate ${extension.id}: ${e.message}`, 'error');
logger.error(`Error on activate extension ${extension.id}:`, e);
});
}
deactivate(id) {
let item = this.list.find(o => o.id == id);
if (!item)
return false;
if (item.extension.isActive && typeof item.deactivate == 'function') {
item.deactivate();
return true;
}
return false;
}
async call(id, method, args) {
let item = this.list.find(o => o.id == id);
if (!item)
return workspace_1.default.showMessage(`extension ${id} not found`, 'error');
let { extension } = item;
if (!extension.isActive) {
workspace_1.default.showMessage(`extension ${id} not activated`, 'error');
return;
}
let { exports } = extension;
if (!exports || !exports.hasOwnProperty(method)) {
workspace_1.default.showMessage(`method ${method} not found on extension ${id}`, 'error');
return;
}
return await Promise.resolve(exports[method].apply(null, args));
}
getExtensionApi(id) {
let item = this.list.find(o => o.id == id);
if (!item)
return null;
let { extension } = item;
return extension.isActive ? extension.exports : null;
}
registerExtension(extension, deactivate) {
let { id, packageJSON } = extension;
this.list.push({ id, extension, deactivate, isLocal: true });
let { contributes } = packageJSON;
if (contributes) {
let { configuration } = contributes;
if (configuration && configuration.properties) {
let { properties } = configuration;
let props = {};
for (let key of Object.keys(properties)) {
let val = properties[key].default;
if (val != null)
props[key] = val;
}
workspace_1.default.configurations.extendsDefaults(props);
}
}
this._onDidLoadExtension.fire(extension);
this.setupActiveEvents(id, packageJSON);
}
get globalExtensions() {
let json = this.loadJson();
if (!json || !json.dependencies)
return [];
return Object.keys(json.dependencies);
}
async globalExtensionStats() {
let json = this.loadJson();
if (!json || !json.dependencies)
return [];
let res = await Promise.all(Object.keys(json.dependencies).map(key => {
return new Promise(async (resolve) => {
try {
let val = json.dependencies[key];
let root = path_1.default.join(this.root, 'node_modules', key);
let jsonFile = path_1.default.join(root, 'package.json');
let stat = await fs_2.statAsync(jsonFile);
if (!stat || !stat.isFile())
return resolve(null);
let content = await fs_2.readFile(jsonFile, 'utf8');
root = await fs_2.realpathAsync(root);
let obj = JSON.parse(content);
let { engines } = obj;
if (!engines || (!engines.hasOwnProperty('coc') && !engines.hasOwnProperty('vscode'))) {
return resolve(null);
}
let version = obj ? obj.version || '' : '';
let description = obj ? obj.description || '' : '';
let uri = isuri_1.default.isValid(val) ? val : null;
resolve({
id: key,
isLocal: false,
version,
description,
exotic: /^https?:/.test(val),
uri,
root,
state: this.getExtensionState(key)
});
}
catch (e) {
logger.error(e);
resolve(null);
}
});
}));
return res.filter(info => info != null);
}
async localExtensionStats(exclude) {
let runtimepath = await workspace_1.default.nvim.eval('&runtimepath');
let included = exclude.map(o => o.root);
let names = exclude.map(o => o.id);
let paths = runtimepath.split(',');
let res = await Promise.all(paths.map(root => {
return new Promise(async (resolve) => {
try {
if (included.includes(root)) {
return resolve(null);
}
let jsonFile = path_1.default.join(root, 'package.json');
let stat = await fs_2.statAsync(jsonFile);
if (!stat || !stat.isFile())
return resolve(null);
let content = await fs_2.readFile(jsonFile, 'utf8');
let obj = JSON.parse(content);
let { engines } = obj;
if (!engines || (!engines.hasOwnProperty('coc') && !engines.hasOwnProperty('vscode'))) {
return resolve(null);
}
if (names.indexOf(obj.name) !== -1) {
workspace_1.default.showMessage(`Skipped extension "${root}", please uninstall "${obj.name}" by :CocUninstall ${obj.name}`, 'warning');
return resolve(null);
}
let version = obj ? obj.version || '' : '';
let description = obj ? obj.description || '' : '';
resolve({
id: obj.name,
isLocal: true,
version,
description,
exotic: false,
root,
state: this.getExtensionState(obj.name)
});
}
catch (e) {
logger.error(e);
resolve(null);
}
});
}));
return res.filter(info => info != null);
}
isGlobalExtension(id) {
return this.globalExtensions.indexOf(id) !== -1;
}
loadJson() {
let { root } = this;
let jsonFile = path_1.default.join(root, 'package.json');
if (!fs_1.default.existsSync(jsonFile))
return null;
return loadJson(jsonFile);
}
get schemes() {
return this._additionalSchemes;
}
addSchemeProperty(key, def) {
this._additionalSchemes[key] = def;
workspace_1.default.configurations.extendsDefaults({ [key]: def.default });
}
setupActiveEvents(id, packageJSON) {
let { activationEvents } = packageJSON;
if (!activationEvents || activationEvents.indexOf('*') !== -1 || !Array.isArray(activationEvents)) {
this.activate(id);
return;
}
let active = () => {
util_2.disposeAll(disposables);
this.activate(id);
active = () => { }; // tslint:disable-line
};
let disposables = [];
for (let eventName of activationEvents) {
let parts = eventName.split(':');
let ev = parts[0];
if (ev == 'onLanguage') {
if (workspace_1.default.filetypes.has(parts[1])) {
active();
return;
}
workspace_1.default.onDidOpenTextDocument(document => {
if (document.languageId == parts[1]) {
active();
}
}, null, disposables);
}
else if (ev == 'onCommand') {
events_1.default.on('Command', command => {
if (command == parts[1]) {
active();
// wait for service ready
return new Promise(resolve => {
setTimeout(resolve, 500);
});
}
}, null, disposables);
}
else if (ev == 'workspaceContains') {
let check = () => {
let folders = workspace_1.default.workspaceFolders.map(o => vscode_uri_1.URI.parse(o.uri).fsPath);
for (let folder of folders) {
if (fs_2.inDirectory(folder, parts[1].split(/\s+/))) {
active();
break;
}
}
};
check();
workspace_1.default.onDidChangeWorkspaceFolders(check, null, disposables);
}
else if (ev == 'onFileSystem') {
for (let doc of workspace_1.default.documents) {
let u = vscode_uri_1.URI.parse(doc.uri);
if (u.scheme == parts[1]) {
return active();
}
}
workspace_1.default.onDidOpenTextDocument(document => {
let u = vscode_uri_1.URI.parse(document.uri);
if (u.scheme == parts[1]) {
active();
}
}, null, disposables);
}
else {
workspace_1.default.showMessage(`Unsupported event ${eventName} of ${id}`, 'error');
}
}
}
createExtension(root, packageJSON, isLocal = false) {
let id = `${packageJSON.name}`;
let isActive = false;
let exports = null;
let filename = path_1.default.join(root, packageJSON.main || 'index.js');
let ext;
let subscriptions = [];
let extension = {
activate: async () => {
if (isActive)
return;
let context = {
subscriptions,
extensionPath: root,
globalState: this.memos.createMemento(`${id}|global`),
workspaceState: this.memos.createMemento(`${id}|${workspace_1.default.rootPath}`),
asAbsolutePath: relativePath => {
return path_1.default.join(root, relativePath);
},
storagePath: path_1.default.join(this.root, `${id}-data`),
logger: createLogger(id)
};
isActive = true;
if (!ext) {
try {
ext = factory_1.createExtension(id, filename);
}
catch (e) {
workspace_1.default.showMessage(`Error on load extension ${id} from ${filename}: ${e}`, 'error');
logger.error(e);
return;
}
}
try {
exports = await Promise.resolve(ext.activate(context));
}
catch (e) {
isActive = false;
workspace_1.default.showMessage(`Error on active extension ${id}: ${e}`, 'error');
logger.error(e);
}
return exports;
}
};
Object.defineProperties(extension, {
id: {
get: () => id
},
packageJSON: {
get: () => packageJSON
},
extensionPath: {
get: () => root
},
isActive: {
get: () => isActive
},
exports: {
get: () => exports
}
});
this.list.push({
id,
isLocal,
extension,
directory: root,
deactivate: () => {
isActive = false;
if (ext && ext.deactivate) {
Promise.resolve(ext.deactivate()).catch(e => {
logger.error(`Error on ${id} deactivate: `, e.message);
});
}
util_2.disposeAll(subscriptions);
subscriptions = [];
}
});
let { contributes } = packageJSON;
if (contributes) {
let { configuration, rootPatterns, commands } = contributes;
if (configuration && configuration.properties) {
let { properties } = configuration;
let props = {};
for (let key of Object.keys(properties)) {
let val = properties[key].default;
if (val != null)
props[key] = val;
}
workspace_1.default.configurations.extendsDefaults(props);
}
if (rootPatterns && rootPatterns.length) {
for (let item of rootPatterns) {
workspace_1.default.addRootPatterns(item.filetype, item.patterns);
}
}
if (commands && commands.length) {
for (let cmd of commands) {
commands_1.default.titles.set(cmd.command, cmd.title);
}
}
}
this._onDidLoadExtension.fire(extension);
if (this.activated) {
this.setupActiveEvents(id, packageJSON);
}
return id;
}
async initializeRoot() {
let root = this.root = await workspace_1.default.nvim.call('coc#util#extension_root');
if (!fs_1.default.existsSync(root)) {
mkdirp_1.default.sync(root);
}
let jsonFile = path_1.default.join(root, 'package.json');
if (!fs_1.default.existsSync(jsonFile)) {
fs_1.default.writeFileSync(jsonFile, '{"dependencies":{}}', 'utf8');
}
if (!this.db) {
let filepath = path_1.default.join(root, 'db.json');
this.db = new db_1.default(filepath);
}
this.manager = new extension_1.default(root);
}
}
exports.Extensions = Extensions;
exports.default = new Extensions();
//# sourceMappingURL=extensions.js.map