diff --git a/package.json b/package.json index 425d0ade785..f06f34a26f9 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "@chemzqm/tsconfig": "0.0.3", "@chemzqm/tslint-config": "^1.0.17", "@types/debounce": "^1.0.0", - "@types/deep-equal": "^1.0.1", "@types/diff": "^3.5.1", "@types/fast-diff": "^1.1.0", "@types/fb-watchman": "^2.0.0", @@ -74,6 +73,7 @@ "@types/semver": "^5.5.0", "@types/uuid": "^3.4.4", "@types/which": "^1.3.1", + "@types/mkdirp": "^0.5.2", "jest": "^23.6.0", "rimraf": "^2.6.2", "ts-jest": "^23.10.3", @@ -82,9 +82,7 @@ }, "dependencies": { "@chemzqm/neovim": "4.3.23", - "@types/mkdirp": "^0.5.2", "debounce": "^1.2.0", - "deep-equal": "^1.0.1", "diff": "^3.5.0", "fast-diff": "^1.1.2", "fb-watchman": "^2.0.0", diff --git a/src/configurations.ts b/src/configurations.ts index 958207380dd..84086205335 100644 --- a/src/configurations.ts +++ b/src/configurations.ts @@ -25,11 +25,11 @@ export default class Configurations { this._configuration = Configurations.parse(data) } - public updateDefaults(key: string, value: any):void { + public updateDefaults(key: string, value: any): void { this._configuration.updateValue(key, value, true) } - public get defaults():any { + public get defaults(): any { return this._configuration.defaults.contents } @@ -40,7 +40,7 @@ export default class Configurations { * @param {string} section * @returns {WorkspaceConfiguration} */ - public getConfiguration(section?: string): WorkspaceConfiguration { + public getConfiguration(section?: string, _resource?: string): WorkspaceConfiguration { const config = Object.freeze(lookUp(this._configuration.getValue(null), section)) diff --git a/src/extensions.ts b/src/extensions.ts index a28abd1d1f0..d5015400e36 100644 --- a/src/extensions.ts +++ b/src/extensions.ts @@ -87,7 +87,7 @@ export class Extensions { }, null, this.disposables) } - public get all():Extension[] { + public get all(): Extension[] { return this.list.map(o => o.extension) } @@ -442,6 +442,19 @@ export class Extensions { disposeAll(subscriptions) } }) + let { contributes } = packageJSON + if (contributes) { + let { configuration } = contributes + if (configuration && configuration.properties) { + let { properties } = configuration + for (let key of Object.keys(properties)) { + let val = properties[key].default + if (val !== undefined) { + (workspace as any)._configurations.updateDefaults(key, val) + } + } + } + } this._onDidLoadExtension.fire(extension) this.setupActiveEvents(id, packageJSON) return id diff --git a/src/model/configuration.ts b/src/model/configuration.ts index c0b73574fbe..b7f750ded46 100644 --- a/src/model/configuration.ts +++ b/src/model/configuration.ts @@ -62,6 +62,7 @@ export class ConfigurationModel implements IConfigurationModel { removeFromValueTree(this.contents, key) } } + export function addToValueTree( settingsTreeRoot: any, key: string, diff --git a/src/plugin.ts b/src/plugin.ts index 84d27b5c0f3..14c744d0faa 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -26,11 +26,6 @@ export default class Plugin extends EventEmitter { services.init() commandManager.init(nvim, this) completion.init(nvim) - this.on('registExtensions', async args => { - for (let folder of args as string[]) { - await extensions.loadExtension(folder) - } - }) clean() // tslint:disable-line } @@ -41,6 +36,11 @@ export default class Plugin extends EventEmitter { await workspace.init() this.handler = new Handler(nvim) await extensions.init(nvim) + this.on('registExtensions', async args => { + for (let folder of args as string[]) { + await extensions.loadExtension(folder) + } + }) await nvim.command('doautocmd User CocNvimInit') logger.info('coc initialized') this.emit('ready') diff --git a/src/types.ts b/src/types.ts index 025aa83ceb0..b0d05cc5194 100644 --- a/src/types.ts +++ b/src/types.ts @@ -54,6 +54,21 @@ export interface ChangeInfo { changedtick: number } +/** + * An event describing the change in Configuration + */ +export interface ConfigurationChangeEvent { + + /** + * Returns `true` if the given section for the given resource (if provided) is affected. + * + * @param section Configuration name, supports _dotted_ names. + * @param resource A resource Uri. + * @return `true` if the given section for the given resource (if provided) is affected. + */ + affectsConfiguration(section: string, resource?: string): boolean +} + export interface LanguageServerConfig { module?: string | ModuleResolve command?: string @@ -651,7 +666,7 @@ export interface IWorkspace { onDidChangeTextDocument: Event onWillSaveTextDocument: Event onDidSaveTextDocument: Event - onDidChangeConfiguration: Event + onDidChangeConfiguration: Event onDidWorkspaceInitialized: Event onWillSaveUntil(callback: (event: TextDocumentWillSaveEvent) => void, thisArg: any, clientId: string): Disposable showMessage(msg: string, identify?: MsgTypes): void diff --git a/src/util/factory.ts b/src/util/factory.ts index 04cac519c55..99dcadab348 100644 --- a/src/util/factory.ts +++ b/src/util/factory.ts @@ -24,8 +24,6 @@ export interface IModule { _nodeModulePaths: (filename: string) => string[] } -const coc = require('../') - const Module: IModule = require('module') const REMOVED_GLOBALS = [ @@ -51,18 +49,18 @@ function removedGlobalStub(name: string): Function { // @see node/lib/internal/module.js function makeRequireFunction(this: any): any { - const require: any = (p: string) => { + const req: any = (p: string) => { if (p === 'coc.nvim') { - return coc + return require('../') } return this.require(p) } - require.resolve = (request: string) => Module._resolveFilename(request, this) - require.main = process.mainModule + req.resolve = (request: string) => Module._resolveFilename(request, this) + req.main = process.mainModule // Enable support to add extra extension types - require.extensions = Module._extensions - require.cache = Module._cache - return require + req.extensions = Module._extensions + req.cache = Module._cache + return req } // @see node/lib/module.js diff --git a/src/workspace.ts b/src/workspace.ts index 3ad5f59f142..66b40ec83f4 100644 --- a/src/workspace.ts +++ b/src/workspace.ts @@ -1,6 +1,5 @@ import { Buffer, NeovimClient as Neovim } from '@chemzqm/neovim' import debounce from 'debounce' -import deepEqual from 'deep-equal' import fs from 'fs' import { parse, ParseError } from 'jsonc-parser' import os from 'os' @@ -16,10 +15,11 @@ import FileSystemWatcher from './model/fileSystemWatcher' import BufferChannel from './model/outputChannel' import Terminal from './model/terminal' import WillSaveUntilHandler from './model/willSaveHandler' -import { ChangeInfo, ConfigurationTarget, EditerState, IConfigurationData, IConfigurationModel, IWorkspace, MsgTypes, OutputChannel, QuickfixItem, TerminalResult, TextDocumentWillSaveEvent, WorkspaceConfiguration } from './types' +import { ChangeInfo, ConfigurationTarget, EditerState, IConfigurationData, IConfigurationModel, IWorkspace, MsgTypes, OutputChannel, QuickfixItem, TerminalResult, TextDocumentWillSaveEvent, WorkspaceConfiguration, ConfigurationChangeEvent } from './types' import { mkdirAsync, renameAsync, resolveRoot, statAsync, writeFile } from './util/fs' import { disposeAll, echoErr, echoMessage, echoWarning, isSupportedScheme, runCommand, watchFiles } from './util/index' import { emptyObject, objectLiteral } from './util/is' +import { equals } from './util/object' import { score } from './util/match' import { byteIndex } from './util/string' import Watchman from './watchman' @@ -52,14 +52,13 @@ export class Workspace implements IWorkspace { private disposables: Disposable[] = [] private configFiles: string[] = [] private checkBuffer: Function & { clear(): void; } - private _settingsScheme: any private _onDidOpenDocument = new Emitter() private _onDidCloseDocument = new Emitter() private _onDidChangeDocument = new Emitter() private _onWillSaveDocument = new Emitter() private _onDidSaveDocument = new Emitter() - private _onDidChangeConfiguration = new Emitter() + private _onDidChangeConfiguration = new Emitter() private _onDidWorkspaceInitialized = new Emitter() public readonly onDidOpenTextDocument: Event = this._onDidOpenDocument.event @@ -67,7 +66,7 @@ export class Workspace implements IWorkspace { public readonly onDidChangeTextDocument: Event = this._onDidChangeDocument.event public readonly onWillSaveTextDocument: Event = this._onWillSaveDocument.event public readonly onDidSaveTextDocument: Event = this._onDidSaveDocument.event - public readonly onDidChangeConfiguration: Event = this._onDidChangeConfiguration.event + public readonly onDidChangeConfiguration: Event = this._onDidChangeConfiguration.event public readonly onDidWorkspaceInitialized: Event = this._onDidWorkspaceInitialized.event constructor() { @@ -80,40 +79,13 @@ export class Workspace implements IWorkspace { logger.error(e.message) }) }, 50) - this._settingsScheme = JSON.parse(fs.readFileSync(path.join(this.pluginRoot, 'data/schema.json'), 'utf8')) this.disposables.push( watchFiles(this.configFiles, this.onConfigurationChange.bind(this)) ) } public async init(): Promise { - let extensions = require('./extensions').default - let jsonSchemas = [] this.terminal = new Terminal(this.nvim) - extensions.onDidLoadExtension(extension => { - let { packageJSON } = extension - let { contributes } = packageJSON - if (!contributes) return - let { jsonValidation, configuration } = contributes - if (configuration) { - let { properties } = configuration - if (properties) { - let props = this._settingsScheme.properties - for (let key of Object.keys(properties)) { - props[key] = properties[key] - let val = properties[key].default - if (val !== undefined) { - this._configurations.updateDefaults(key, val) - } - } - } - } - if (jsonValidation && jsonValidation.length) { - jsonSchemas.push(...jsonValidation) - this._configurations.updateDefaults('json.schemas', jsonSchemas) - } - }, null, this.disposables) - events.on('BufEnter', bufnr => { this.bufnr = bufnr }, null, this.disposables) @@ -235,10 +207,6 @@ export class Workspace implements IWorkspace { return this._initialized } - public get settingsScheme(): any { - return this._settingsScheme - } - public get ready(): Promise { if (this._initialized) return Promise.resolve() return new Promise(resolve => { @@ -278,9 +246,9 @@ export class Workspace implements IWorkspace { ) } - public getConfiguration(section?: string, _resource?: string): WorkspaceConfiguration { + public getConfiguration(section?: string, resource?: string): WorkspaceConfiguration { // TODO support resource - return this._configurations.getConfiguration(section) + return this._configurations.getConfiguration(section, resource) } public getDocument(uri: string | number): Document @@ -713,8 +681,13 @@ export class Workspace implements IWorkspace { let { _configurations } = this let config = this.loadConfigurations() this._configurations = new Configurations(config, this.configurationShape) - if (!_configurations || !deepEqual(_configurations, this._configurations)) { - this._onDidChangeConfiguration.fire(this.getConfiguration()) + if (!_configurations || !equals(_configurations, this._configurations)) { + this._onDidChangeConfiguration.fire({ + affectsConfiguration: (section: string, resource?: string): boolean => { + return equals(_configurations.getConfiguration(section, resource), + this._configurations.getConfiguration(section, resource)) + } + }) } } @@ -795,7 +768,7 @@ export class Workspace implements IWorkspace { let file = path.join(this.pluginRoot, 'settings.json') this.configFiles.push(file) let defaultConfig: IConfigurationModel = this.getDefaultConfiguration(file) - let home = process.env.VIMCONFIG + let home = process.env.VIMCONFIG || path.join(os.homedir(), '.vim') if (global.hasOwnProperty('__TEST__')) { home = path.join(this.pluginRoot, 'src/__tests__') } diff --git a/yarn.lock b/yarn.lock index 9d1faab5947..7ec37087950 100644 --- a/yarn.lock +++ b/yarn.lock @@ -115,10 +115,6 @@ version "1.0.0" resolved "https://registry.yarnpkg.com/@types/debounce/-/debounce-1.0.0.tgz#417560200331e1bb84d72da85391102c2fcd61b7" -"@types/deep-equal@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/deep-equal/-/deep-equal-1.0.1.tgz#71cfabb247c22bcc16d536111f50c0ed12476b03" - "@types/diff@^3.5.1": version "3.5.1" resolved "https://registry.yarnpkg.com/@types/diff/-/diff-3.5.1.tgz#30253f6e177564ad7da707b1ebe46d3eade71706" @@ -815,10 +811,6 @@ decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" -deep-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"