diff --git a/build/index.js b/build/index.js index 0a1341912c8..c2ef6f459d3 100644 --- a/build/index.js +++ b/build/index.js @@ -10313,7 +10313,7 @@ const log4js_1 = tslib_1.__importDefault(__webpack_require__(5)); const events_1 = tslib_1.__importDefault(__webpack_require__(149)); const plugin_1 = tslib_1.__importDefault(__webpack_require__(246)); const semver_1 = tslib_1.__importDefault(__webpack_require__(1)); -__webpack_require__(312); +__webpack_require__(314); const vscode_uri_1 = __webpack_require__(183); const logger = __webpack_require__(2)('attach'); const isTest = "none" == 'test'; @@ -35021,16 +35021,16 @@ const tslib_1 = __webpack_require__(3); const events_1 = __webpack_require__(137); const vscode_languageserver_types_1 = __webpack_require__(162); const commands_1 = tslib_1.__importDefault(__webpack_require__(247)); -const completion_1 = tslib_1.__importDefault(__webpack_require__(251)); +const completion_1 = tslib_1.__importDefault(__webpack_require__(253)); const cursors_1 = tslib_1.__importDefault(__webpack_require__(405)); -const manager_1 = tslib_1.__importDefault(__webpack_require__(319)); -const extensions_1 = tslib_1.__importDefault(__webpack_require__(253)); +const manager_1 = tslib_1.__importDefault(__webpack_require__(248)); +const extensions_1 = tslib_1.__importDefault(__webpack_require__(255)); const handler_1 = tslib_1.__importDefault(__webpack_require__(407)); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); -const manager_2 = tslib_1.__importDefault(__webpack_require__(370)); -const services_1 = tslib_1.__importDefault(__webpack_require__(354)); -const manager_3 = tslib_1.__importDefault(__webpack_require__(248)); -const sources_1 = tslib_1.__importDefault(__webpack_require__(252)); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); +const manager_2 = tslib_1.__importDefault(__webpack_require__(365)); +const services_1 = tslib_1.__importDefault(__webpack_require__(349)); +const manager_3 = tslib_1.__importDefault(__webpack_require__(250)); +const sources_1 = tslib_1.__importDefault(__webpack_require__(254)); const types_1 = __webpack_require__(192); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); const logger = __webpack_require__(2)('plugin'); @@ -35280,7 +35280,7 @@ class Plugin extends events_1.EventEmitter { return false; } get version() { - return workspace_1.default.version + ( true ? '-' + "9e9b0ad3a2" : undefined); + return workspace_1.default.version + ( true ? '-' + "857c221c55" : undefined); } async showInfo() { if (!this.infoChannel) { @@ -35488,11 +35488,11 @@ exports.default = Plugin; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); +const vscode_uri_1 = __webpack_require__(183); +const manager_1 = tslib_1.__importDefault(__webpack_require__(248)); +const manager_2 = tslib_1.__importDefault(__webpack_require__(250)); const util_1 = __webpack_require__(177); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const manager_1 = tslib_1.__importDefault(__webpack_require__(248)); -const manager_2 = tslib_1.__importDefault(__webpack_require__(319)); -const vscode_uri_1 = __webpack_require__(183); const logger = __webpack_require__(2)('commands'); class CommandItem { constructor(id, impl, thisArg, internal = false) { @@ -35538,7 +35538,7 @@ class CommandManager { await nvim.call('coc#_cancel', []); if (doc.dirty) doc.forceSync(); - await manager_1.default.insertSnippet(edit.newText, true, edit.range); + await manager_2.default.insertSnippet(edit.newText, true, edit.range); } }, true); this.register({ @@ -35641,7 +35641,7 @@ class CommandManager { this.register({ id: 'workspace.diagnosticRelated', execute: () => { - return manager_2.default.jumpRelated(); + return manager_1.default.jumpRelated(); } }, false, 'jump to related locations of current diagnostic.'); this.register({ @@ -35834,5505 +35834,5210 @@ exports.default = new CommandManager(); Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); +const vscode_languageserver_protocol_1 = __webpack_require__(150); +const vscode_uri_1 = __webpack_require__(183); const events_1 = tslib_1.__importDefault(__webpack_require__(149)); +const floatFactory_1 = tslib_1.__importDefault(__webpack_require__(249)); +const util_1 = __webpack_require__(177); +const position_1 = __webpack_require__(216); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const Snippets = tslib_1.__importStar(__webpack_require__(249)); -const parser_1 = __webpack_require__(249); -const session_1 = __webpack_require__(250); -const variableResolve_1 = __webpack_require__(404); -const logger = __webpack_require__(2)('snippets-manager'); -class SnippetManager { +const buffer_1 = __webpack_require__(401); +const collection_1 = tslib_1.__importDefault(__webpack_require__(404)); +const util_2 = __webpack_require__(403); +const logger = __webpack_require__(2)('diagnostic-manager'); +class DiagnosticManager { constructor() { - this.sessionMap = new Map(); + this.enabled = true; + this.buffers = []; + this.lastMessage = ''; + this.collections = []; this.disposables = []; - // tslint:disable-next-line:no-floating-promises - workspace_1.default.ready.then(() => { - let config = workspace_1.default.getConfiguration('coc.preferences'); - this.statusItem = workspace_1.default.createStatusBarItem(0); - this.statusItem.text = config.get('snippetStatusText', 'SNIP'); - }); - workspace_1.default.onDidChangeTextDocument(async (e) => { - let { uri } = e.textDocument; - let doc = workspace_1.default.getDocument(uri); - if (!doc) + this.lastChanageTs = 0; + } + init() { + this.setConfiguration(); + let { nvim } = workspace_1.default; + let { maxWindowHeight, maxWindowWidth } = this.config; + this.floatFactory = new floatFactory_1.default(nvim, workspace_1.default.env, false, maxWindowHeight, maxWindowWidth); + this.disposables.push(vscode_languageserver_protocol_1.Disposable.create(() => { + if (this.timer) + clearTimeout(this.timer); + })); + events_1.default.on('CursorMoved', async () => { + if (this.timer) + clearTimeout(this.timer); + this.timer = setTimeout(async () => { + if (this.config.enableMessage != 'always') + return; + await this.echoMessage(true); + }, this.config.messageDelay); + }, null, this.disposables); + events_1.default.on('InsertEnter', async () => { + if (this.timer) + clearTimeout(this.timer); + this.floatFactory.close(); + }, null, this.disposables); + events_1.default.on('InsertLeave', async (bufnr) => { + this.floatFactory.close(); + let doc = workspace_1.default.getDocument(bufnr); + if (!doc || !this.shouldValidate(doc)) return; - let session = this.getSession(doc.bufnr); - if (session && session.isActive) { - await session.synchronizeUpdatedPlaceholders(e.contentChanges[0]); + let { refreshOnInsertMode, refreshAfterSave } = this.config; + if (!refreshOnInsertMode && !refreshAfterSave) { + if (doc.dirty) { + doc.forceSync(); + await util_1.wait(50); + } + let d = 300 - (Date.now() - this.lastChanageTs); + if (d > 0) + await util_1.wait(d); + this.refreshBuffer(doc.uri); } }, null, this.disposables); - workspace_1.default.onDidCloseTextDocument(textDocument => { - let doc = workspace_1.default.getDocument(textDocument.uri); - if (!doc) + events_1.default.on('BufEnter', async () => { + if (this.timer) + clearTimeout(this.timer); + if (!this.enabled || !this.config.locationlist) return; - let session = this.getSession(doc.bufnr); - if (session) - session.deactivate(); - }, null, this.disposables); - events_1.default.on('BufEnter', async (bufnr) => { - let session = this.getSession(bufnr); - if (!this.statusItem) + let doc = await workspace_1.default.document; + if (!doc || doc.buftype == 'quickfix') return; - if (session && session.isActive) { - this.statusItem.show(); + if (this.shouldValidate(doc)) { + let refreshed = this.refreshBuffer(doc.uri); + if (refreshed) + return; } - else { - this.statusItem.hide(); + let curr = await nvim.eval(`getloclist(win_getid(),{'title':1})`); + if (curr.title && curr.title.indexOf('Diagnostics of coc') != -1) { + await nvim.eval(`setloclist(win_getid(),[],'f')`); } }, null, this.disposables); - events_1.default.on('InsertEnter', async () => { - let { session } = this; - if (!session) + events_1.default.on('BufWritePost', async (bufnr) => { + let buf = this.buffers.find(buf => buf.bufnr == bufnr); + if (buf) + await buf.checkSigns(); + await util_1.wait(100); + if (this.config.refreshAfterSave) { + this.refreshBuffer(buf.uri); + } + }, null, this.disposables); + events_1.default.on(['TextChanged', 'TextChangedI'], () => { + this.lastChanageTs = Date.now(); + }, null, this.disposables); + workspace_1.default.onDidChangeConfiguration(async (e) => { + this.setConfiguration(e); + }, null, this.disposables); + // create buffers + for (let doc of workspace_1.default.documents) { + this.createDiagnosticBuffer(doc); + } + workspace_1.default.onDidOpenTextDocument(textDocument => { + let doc = workspace_1.default.getDocument(textDocument.uri); + this.createDiagnosticBuffer(doc); + }, null, this.disposables); + workspace_1.default.onDidCloseTextDocument(({ uri }) => { + let doc = workspace_1.default.getDocument(uri); + if (!doc) return; - await session.checkPosition(); + this.disposeBuffer(doc.bufnr); }, null, this.disposables); - } - /** - * Insert snippet at current cursor position - */ - async insertSnippet(snippet, select = true, range) { - let { nvim } = workspace_1.default; - let bufnr = await nvim.call('bufnr', '%'); - let session = this.getSession(bufnr); - if (!session) { - session = new session_1.SnippetSession(workspace_1.default.nvim, bufnr); - this.sessionMap.set(bufnr, session); - session.onCancel(() => { - this.sessionMap.delete(bufnr); - if (workspace_1.default.bufnr == bufnr) { - this.statusItem.hide(); - } - }); + this.setConfigurationErrors(true); + workspace_1.default.configurations.onError(async () => { + this.setConfigurationErrors(); + }, null, this.disposables); + let { errorSign, warningSign, infoSign, hintSign } = this.config; + nvim.pauseNotification(); + let signError = `sign define CocError linehl=CocErrorLine texthl=CocErrorSign`; + let signWarning = `sign define CocWarning linehl=CocWarningLine texthl=CocWarningSign`; + let signInfo = `sign define CocInfo linehl=CocInfoLine texthl=CocInfoSign`; + let signHint = `sign define CocHint linehl=CocHintLine texthl=CocHintSign`; + if (this.config.enableSign) { + signError += ` text=${errorSign}`; + signWarning += ` text=${warningSign}`; + signInfo += ` text=${infoSign}`; + signHint += ` text=${hintSign}`; } - let isActive = await session.start(snippet, select, range); - if (isActive) { - this.statusItem.show(); + if (workspace_1.default.isNvim && this.config.enableHighlightLineNumber) { + signError += ' numhl=CocErrorSign'; + signWarning += ' numhl=CocWarningSign'; + signInfo += ' numhl=CocInfoSign'; + signHint += ' numhl=CocHintSign'; } - else if (session) { - session.deactivate(); + nvim.command(signError, true); + nvim.command(signWarning, true); + nvim.command(signInfo, true); + nvim.command(signHint, true); + if (this.config.virtualText && workspace_1.default.isNvim) { + nvim.call('coc#util#init_virtual_hl', [], true); } - nvim.command('silent! unlet g:coc_last_placeholder g:coc_selected_text', true); - return isActive; + nvim.resumeNotification(false, true).logError(); } - isPlainText(text) { - let snippet = (new parser_1.SnippetParser()).parse(text, true); - if (snippet.placeholders.every(p => p.isFinalTabstop == true && p.toString() == '')) { - return true; + createDiagnosticBuffer(doc) { + if (!this.shouldValidate(doc)) + return; + let idx = this.buffers.findIndex(b => b.bufnr == doc.bufnr); + if (idx == -1) { + let buf = new buffer_1.DiagnosticBuffer(doc.bufnr, this.config); + this.buffers.push(buf); + buf.onDidRefresh(() => { + if (workspace_1.default.insertMode) + return; + this.echoMessage(true).logError(); + }); } - return false; - } - async selectCurrentPlaceholder(triggerAutocmd = true) { - let { session } = this; - if (session) - return await session.selectCurrentPlaceholder(triggerAutocmd); - } - async nextPlaceholder() { - let { session } = this; - if (session) - return await session.nextPlaceholder(); - workspace_1.default.nvim.call('coc#snippet#disable', [], true); - this.statusItem.hide(); - } - async previousPlaceholder() { - let { session } = this; - if (session) - return await session.previousPlaceholder(); - workspace_1.default.nvim.call('coc#snippet#disable', [], true); - this.statusItem.hide(); - } - cancel() { - let session = this.getSession(workspace_1.default.bufnr); - if (session) - return session.deactivate(); - workspace_1.default.nvim.call('coc#snippet#disable', [], true); - if (this.statusItem) - this.statusItem.hide(); } - get session() { - let session = this.getSession(workspace_1.default.bufnr); - return session && session.isActive ? session : null; - } - isActived(bufnr) { - let session = this.getSession(bufnr); - return session && session.isActive; - } - jumpable() { - let { session } = this; - if (!session) - return false; - let placeholder = session.placeholder; - if (placeholder && !placeholder.isFinalTabstop) { - return true; + setConfigurationErrors(init) { + let collections = this.collections; + let collection = collections.find(o => o.name == 'config'); + if (!collection) { + collection = this.create('config'); } - return false; - } - getSession(bufnr) { - return this.sessionMap.get(bufnr); - } - async resolveSnippet(body) { - let parser = new Snippets.SnippetParser(); - const snippet = parser.parse(body, true); - const resolver = new variableResolve_1.SnippetVariableResolver(); - snippet.resolveVariables(resolver); - return snippet; - } - dispose() { - this.cancel(); - for (let d of this.disposables) { - d.dispose(); + else { + collection.clear(); + } + let { errorItems } = workspace_1.default.configurations; + if (errorItems && errorItems.length) { + if (init) + workspace_1.default.showMessage(`settings file parse error, run ':CocList diagnostics'`, 'error'); + let entries = new Map(); + for (let item of errorItems) { + let { uri } = item.location; + let diagnostics = entries.get(uri) || []; + diagnostics.push(vscode_languageserver_protocol_1.Diagnostic.create(item.location.range, item.message, vscode_languageserver_protocol_1.DiagnosticSeverity.Error)); + entries.set(uri, diagnostics); + } + collection.set(Array.from(entries)); } } -} -exports.SnippetManager = SnippetManager; -exports.default = new SnippetManager(); -//# sourceMappingURL=manager.js.map - -/***/ }), -/* 249 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -Object.defineProperty(exports, "__esModule", { value: true }); -const vscode_languageserver_protocol_1 = __webpack_require__(150); -const logger = __webpack_require__(2)('snippets-parser'); -class Scanner { - constructor() { - this.text(''); + /** + * Create collection by name + */ + create(name) { + let collection = new collection_1.default(name); + this.collections.push(collection); + // Used for refresh diagnostics on buferEnter when refreshAfterSave is true + // Note we can't make sure it work as expected when there're multiple sources + let createTime = Date.now(); + let refreshed = false; + collection.onDidDiagnosticsChange(async (uri) => { + if (this.config.refreshAfterSave && + (refreshed || Date.now() - createTime > 5000)) + return; + refreshed = true; + this.refreshBuffer(uri); + }); + collection.onDidDiagnosticsClear(uris => { + for (let uri of uris) { + this.refreshBuffer(uri); + } + }); + collection.onDispose(() => { + let idx = this.collections.findIndex(o => o == collection); + if (idx !== -1) + this.collections.splice(idx, 1); + }); + return collection; } - static isDigitCharacter(ch) { - return ch >= 48 /* Digit0 */ && ch <= 57 /* Digit9 */; + /** + * Get diagnostics ranges from document + */ + getSortedRanges(uri, severity) { + let collections = this.getCollections(uri); + let res = []; + let level = severity ? util_2.severityLevel(severity) : 0; + for (let collection of collections) { + let diagnostics = collection.get(uri); + if (level) + diagnostics = diagnostics.filter(o => o.severity == level); + let ranges = diagnostics.map(o => o.range); + res.push(...ranges); + } + res.sort((a, b) => { + if (a.start.line != b.start.line) { + return a.start.line - b.start.line; + } + return a.start.character - b.start.character; + }); + return res; } - static isVariableCharacter(ch) { - return ch === 95 /* Underline */ - || (ch >= 97 /* a */ && ch <= 122 /* z */) - || (ch >= 65 /* A */ && ch <= 90 /* Z */); + /** + * Get readonly diagnostics for a buffer + */ + getDiagnostics(uri) { + let collections = this.getCollections(uri); + let { level } = this.config; + let res = []; + for (let collection of collections) { + let items = collection.get(uri); + if (!items) + continue; + if (level && level < vscode_languageserver_protocol_1.DiagnosticSeverity.Hint) { + items = items.filter(s => s.severity == null || s.severity <= level); + } + res.push(...items); + } + res.sort((a, b) => { + if (a.severity == b.severity) { + let d = position_1.comparePosition(a.range.start, b.range.start); + if (d != 0) + return d; + if (a.source == b.source) + return a.message > b.message ? 1 : -1; + return a.source > b.source ? 1 : -1; + } + return a.severity - b.severity; + }); + return res; } - text(value) { - this.value = value; - this.pos = 0; + getDiagnosticsInRange(document, range) { + let collections = this.getCollections(document.uri); + let res = []; + for (let collection of collections) { + let items = collection.get(document.uri); + if (!items) + continue; + for (let item of items) { + if (position_1.rangeIntersect(item.range, range)) { + res.push(item); + } + } + } + return res; } - tokenText(token) { - return this.value.substr(token.pos, token.len); + /** + * Show diagnostics under curosr in preview window + */ + async preview() { + let [bufnr, cursor] = await this.nvim.eval('[bufnr("%"),coc#util#cursor()]'); + let { nvim } = this; + let diagnostics = await this.getDiagnosticsAt(bufnr, cursor); + if (diagnostics.length == 0) { + nvim.command('pclose', true); + workspace_1.default.showMessage(`Empty diagnostics`, 'warning'); + return; + } + let lines = []; + for (let diagnostic of diagnostics) { + let { source, code, severity, message } = diagnostic; + let s = util_2.getSeverityName(severity)[0]; + lines.push(`[${source}${code ? ' ' + code : ''}] [${s}]`); + lines.push(...message.split(/\r?\n/)); + lines.push(''); + } + lines = lines.slice(0, -1); + // let content = lines.join('\n').trim() + nvim.call('coc#util#preview_info', [lines, 'txt'], true); } - next() { - if (this.pos >= this.value.length) { - return { type: 14 /* EOF */, pos: this.pos, len: 0 }; + /** + * Jump to previous diagnostic position + */ + async jumpPrevious(severity) { + let buffer = await this.nvim.buffer; + let document = workspace_1.default.getDocument(buffer.id); + if (!document) + return; + let offset = await workspace_1.default.getOffset(); + if (offset == null) + return; + let ranges = this.getSortedRanges(document.uri, severity); + if (ranges.length == 0) { + workspace_1.default.showMessage('Empty diagnostics', 'warning'); + return; } - let pos = this.pos; - let len = 0; - let ch = this.value.charCodeAt(pos); - let type; - // static types - type = Scanner._table[ch]; - if (typeof type === 'number') { - this.pos += 1; - return { type, pos, len: 1 }; + let { textDocument } = document; + for (let i = ranges.length - 1; i >= 0; i--) { + if (textDocument.offsetAt(ranges[i].end) < offset) { + await workspace_1.default.moveTo(ranges[i].start); + return; + } } - // number - if (Scanner.isDigitCharacter(ch)) { - type = 8 /* Int */; - do { - len += 1; - ch = this.value.charCodeAt(pos + len); - } while (Scanner.isDigitCharacter(ch)); - this.pos += len; - return { type, pos, len }; + if (await this.nvim.getOption('wrapscan')) { + await workspace_1.default.moveTo(ranges[ranges.length - 1].start); } - // variable name - if (Scanner.isVariableCharacter(ch)) { - type = 9 /* VariableName */; - do { - ch = this.value.charCodeAt(pos + (++len)); - } while (Scanner.isVariableCharacter(ch) || Scanner.isDigitCharacter(ch)); - this.pos += len; - return { type, pos, len }; + } + /** + * Jump to next diagnostic position + */ + async jumpNext(severity) { + let buffer = await this.nvim.buffer; + let document = workspace_1.default.getDocument(buffer.id); + let offset = await workspace_1.default.getOffset(); + let ranges = this.getSortedRanges(document.uri, severity); + if (ranges.length == 0) { + workspace_1.default.showMessage('Empty diagnostics', 'warning'); + return; + } + let { textDocument } = document; + for (let i = 0; i <= ranges.length - 1; i++) { + if (textDocument.offsetAt(ranges[i].start) > offset) { + await workspace_1.default.moveTo(ranges[i].start); + return; + } + } + if (await this.nvim.getOption('wrapscan')) { + await workspace_1.default.moveTo(ranges[0].start); } - // format - type = 10 /* Format */; - do { - len += 1; - ch = this.value.charCodeAt(pos + len); - } while (!isNaN(ch) - && typeof Scanner._table[ch] === 'undefined' // not static token - && !Scanner.isDigitCharacter(ch) // not number - && !Scanner.isVariableCharacter(ch) // not variable - ); - this.pos += len; - return { type, pos, len }; } -} -exports.Scanner = Scanner; -Scanner._table = { - [36 /* DollarSign */]: 0 /* Dollar */, - [58 /* Colon */]: 1 /* Colon */, - [44 /* Comma */]: 2 /* Comma */, - [123 /* OpenCurlyBrace */]: 3 /* CurlyOpen */, - [125 /* CloseCurlyBrace */]: 4 /* CurlyClose */, - [92 /* Backslash */]: 5 /* Backslash */, - [47 /* Slash */]: 6 /* Forwardslash */, - [124 /* Pipe */]: 7 /* Pipe */, - [43 /* Plus */]: 11 /* Plus */, - [45 /* Dash */]: 12 /* Dash */, - [63 /* QuestionMark */]: 13 /* QuestionMark */, -}; -class Marker { - constructor() { - this._children = []; - } - appendChild(child) { - if (child instanceof Text && this._children[this._children.length - 1] instanceof Text) { - // this and previous child are text -> merge them - this._children[this._children.length - 1].value += child.value; - } - else { - // normal adoption of child - child.parent = this; - this._children.push(child); + /** + * All diagnostics of current workspace + */ + getDiagnosticList() { + let res = []; + for (let collection of this.collections) { + collection.forEach((uri, diagnostics) => { + let file = vscode_uri_1.URI.parse(uri).fsPath; + for (let diagnostic of diagnostics) { + let { start } = diagnostic.range; + let o = { + file, + lnum: start.line + 1, + col: start.character + 1, + message: `[${diagnostic.source || collection.name}${diagnostic.code ? ' ' + diagnostic.code : ''}] ${diagnostic.message}`, + severity: util_2.getSeverityName(diagnostic.severity), + level: diagnostic.severity || 0, + location: vscode_languageserver_protocol_1.Location.create(uri, diagnostic.range) + }; + res.push(o); + } + }); } - return this; - } - setOnlyChild(child) { - child.parent = this; - this._children = [child]; - } - replace(child, others) { - const { parent } = child; - const idx = parent.children.indexOf(child); - const newChildren = parent.children.slice(0); - newChildren.splice(idx, 1, ...others); - parent._children = newChildren; - (function _fixParent(children, parent) { - for (const child of children) { - child.parent = parent; - _fixParent(child.children, child); + res.sort((a, b) => { + if (a.level !== b.level) { + return a.level - b.level; } - })(others, parent); - } - get children() { - return this._children; - } - get snippet() { - let candidate = this; - while (true) { - if (!candidate) { - return undefined; + if (a.file !== b.file) { + return a.file > b.file ? 1 : -1; } - if (candidate instanceof TextmateSnippet) { - return candidate; + else { + if (a.lnum != b.lnum) { + return a.lnum - b.lnum; + } + return a.col - b.col; } - candidate = candidate.parent; - } - } - toString() { - return this.children.reduce((prev, cur) => prev + cur.toString(), ''); - } - len() { - return 0; - } - get next() { - let { parent } = this; - let { children } = parent; - let idx = children.indexOf(this); - return children[idx + 1]; - } -} -exports.Marker = Marker; -class Text extends Marker { - constructor(value) { - super(); - this.value = value; - } - static escape(value) { - return value.replace(/\$|}|\\/g, '\\$&'); - } - toString() { - return this.value; - } - toTextmateString() { - return Text.escape(this.value); - } - len() { - return this.value.length; - } - clone() { - return new Text(this.value); - } -} -exports.Text = Text; -class TransformableMarker extends Marker { -} -exports.TransformableMarker = TransformableMarker; -class Placeholder extends TransformableMarker { - constructor(index) { - super(); - this.index = index; + }); + return res; } - static compareByIndex(a, b) { - if (a.index === b.index) { - return 0; - } - else if (a.isFinalTabstop) { - return 1; - } - else if (b.isFinalTabstop) { - return -1; - } - else if (a.index < b.index) { - return -1; - } - else if (a.index > b.index) { - return 1; - } - else { - return 0; + async getDiagnosticsAt(bufnr, cursor) { + let pos = vscode_languageserver_protocol_1.Position.create(cursor[0], cursor[1]); + let buffer = this.buffers.find(o => o.bufnr == bufnr); + if (!buffer) + return []; + let { checkCurrentLine } = this.config; + let diagnostics = buffer.diagnostics.filter(o => position_1.positionInRange(pos, o.range) == 0); + if (diagnostics.length == 0 && checkCurrentLine) { + diagnostics = buffer.diagnostics.filter(o => position_1.lineInRange(pos.line, o.range)); } + diagnostics.sort((a, b) => a.severity - b.severity); + return diagnostics; } - get isFinalTabstop() { - return this.index === 0; - } - get choice() { - return this._children.length === 1 && this._children[0] instanceof Choice - ? this._children[0] - : undefined; + async getCurrentDiagnostics() { + let [bufnr, cursor] = await this.nvim.eval('[bufnr("%"),coc#util#cursor()]'); + return await this.getDiagnosticsAt(bufnr, cursor); } - toTextmateString() { - let transformString = ''; - if (this.transform) { - transformString = this.transform.toTextmateString(); + /** + * Echo diagnostic message of currrent position + */ + async echoMessage(truncate = false) { + const config = this.config; + if (!this.enabled || config.enableMessage == 'never') + return; + if (this.timer) + clearTimeout(this.timer); + let useFloat = config.messageTarget == 'float'; + let [bufnr, cursor] = await this.nvim.eval('[bufnr("%"),coc#util#cursor()]'); + if (useFloat) { + let { buffer } = this.floatFactory; + if (buffer && bufnr == buffer.id) + return; } - if (this.children.length === 0 && !this.transform) { - return `\$${this.index}`; + let diagnostics = await this.getDiagnosticsAt(bufnr, cursor); + if (diagnostics.length == 0) { + if (useFloat) { + this.floatFactory.close(); + } + else { + let echoLine = await this.nvim.call('coc#util#echo_line'); + if (this.lastMessage && echoLine.startsWith(this.lastMessage)) { + this.nvim.command('echo ""', true); + } + } + return; } - else if (this.children.length === 0) { - return `\${${this.index}${transformString}}`; + if (truncate && workspace_1.default.insertMode) + return; + let docs = []; + let ft = ''; + if (Object.keys(config.filetypeMap).length > 0) { + const filetype = await this.nvim.eval('&filetype'); + const defaultFiletype = config.filetypeMap['default'] || ''; + ft = config.filetypeMap[filetype] || (defaultFiletype == 'bufferType' ? filetype : defaultFiletype); } - else if (this.choice) { - return `\${${this.index}|${this.choice.toTextmateString()}|${transformString}}`; + diagnostics.forEach(diagnostic => { + let { source, code, severity, message } = diagnostic; + let s = util_2.getSeverityName(severity)[0]; + const codeStr = code ? ' ' + code : ''; + const str = config.format.replace('%source', source).replace('%code', codeStr).replace('%severity', s).replace('%message', message); + let filetype = 'Error'; + if (ft === '') { + switch (severity) { + case vscode_languageserver_protocol_1.DiagnosticSeverity.Hint: + filetype = 'Hint'; + break; + case vscode_languageserver_protocol_1.DiagnosticSeverity.Warning: + filetype = 'Warning'; + break; + case vscode_languageserver_protocol_1.DiagnosticSeverity.Information: + filetype = 'Info'; + break; + } + } + else { + filetype = ft; + } + docs.push({ filetype, content: str }); + }); + if (useFloat) { + await this.floatFactory.create(docs); } else { - return `\${${this.index}:${this.children.map(child => child.toTextmateString()).join('')}${transformString}}`; - } - } - clone() { - let ret = new Placeholder(this.index); - if (this.transform) { - ret.transform = this.transform.clone(); + let lines = docs.map(d => d.content).join('\n').split(/\r?\n/); + if (lines.length) { + await this.nvim.command('echo ""'); + this.lastMessage = lines[0].slice(0, 30); + await workspace_1.default.echoLines(lines, truncate); + } } - ret._children = this.children.map(child => child.clone()); - return ret; } -} -exports.Placeholder = Placeholder; -class Choice extends Marker { - constructor() { - super(...arguments); - this.options = []; - } - appendChild(marker) { - if (marker instanceof Text) { - marker.parent = this; - this.options.push(marker); + async jumpRelated() { + let diagnostics = await this.getCurrentDiagnostics(); + if (!diagnostics) + return; + let diagnostic = diagnostics.find(o => o.relatedInformation != null); + if (!diagnostic) + return; + let locations = diagnostic.relatedInformation.map(o => o.location); + if (locations.length == 1) { + await workspace_1.default.jumpTo(locations[0].uri, locations[0].range.start); } - return this; - } - toString() { - return this.options[0].value; - } - toTextmateString() { - return this.options - .map(option => option.value.replace(/\||,/g, '\\$&')) - .join(','); - } - len() { - return this.options[0].len(); - } - clone() { - let ret = new Choice(); - for (let opt of this.options) { - ret.appendChild(opt); + else if (locations.length > 1) { + await workspace_1.default.showLocations(locations); } - return ret; } -} -exports.Choice = Choice; -class Transform extends Marker { - resolve(value) { - let didMatch = false; - let ret = value.replace(this.regexp, (...args) => { - didMatch = true; - return this._replace(args.slice(0, -2)); - }); - // when the regex didn't match and when the transform has - // else branches, then run those - if (!didMatch && this._children.some(child => child instanceof FormatString && Boolean(child.elseValue))) { - ret = this._replace([]); + disposeBuffer(bufnr) { + let idx = this.buffers.findIndex(buf => buf.bufnr == bufnr); + if (idx == -1) + return; + let buf = this.buffers[idx]; + buf.dispose(); + this.buffers.splice(idx, 1); + for (let collection of this.collections) { + collection.delete(buf.uri); } - return ret; + buf.clear().logError(); } - _replace(groups) { - let ret = ''; - for (const marker of this._children) { - if (marker instanceof FormatString) { - let value = groups[marker.index] || ''; - value = marker.resolve(value); - ret += value; - } - else { - ret += marker.toString(); - } + hideFloat() { + if (this.floatFactory) { + this.floatFactory.close(); } - return ret; - } - toString() { - return ''; - } - toTextmateString() { - return `/${this.regexp.source}/${this.children.map(c => c.toTextmateString())}/${(this.regexp.ignoreCase ? 'i' : '') + (this.regexp.global ? 'g' : '')}`; - } - clone() { - let ret = new Transform(); - ret.regexp = new RegExp(this.regexp.source, '' + (this.regexp.ignoreCase ? 'i' : '') + (this.regexp.global ? 'g' : '')); - ret._children = this.children.map(child => child.clone()); - return ret; - } -} -exports.Transform = Transform; -class FormatString extends Marker { - constructor(index, shorthandName, ifValue, elseValue) { - super(); - this.index = index; - this.shorthandName = shorthandName; - this.ifValue = ifValue; - this.elseValue = elseValue; } - resolve(value) { - if (this.shorthandName === 'upcase') { - return !value ? '' : value.toLocaleUpperCase(); - } - else if (this.shorthandName === 'downcase') { - return !value ? '' : value.toLocaleLowerCase(); - } - else if (this.shorthandName === 'capitalize') { - return !value ? '' : (value[0].toLocaleUpperCase() + value.substr(1)); - } - else if (this.shorthandName === 'pascalcase') { - return !value ? '' : this._toPascalCase(value); - } - else if (Boolean(value) && typeof this.ifValue === 'string') { - return this.ifValue; - } - else if (!Boolean(value) && typeof this.elseValue === 'string') { - return this.elseValue; + dispose() { + for (let collection of this.collections) { + collection.dispose(); } - else { - return value || ''; + if (this.floatFactory) { + this.floatFactory.dispose(); } + this.buffers.splice(0, this.buffers.length); + this.collections = []; + util_1.disposeAll(this.disposables); } - _toPascalCase(value) { - const match = value.match(/[a-z]+/gi); - if (!match) { - return value; - } - return match.map(word => { - return word.charAt(0).toUpperCase() - + word.substr(1).toLowerCase(); - }) - .join(''); + get nvim() { + return workspace_1.default.nvim; } - toTextmateString() { - let value = '${'; - value += this.index; - if (this.shorthandName) { - value += `:/${this.shorthandName}`; + setConfiguration(event) { + if (event && !event.affectsConfiguration('diagnostic')) + return; + let preferences = workspace_1.default.getConfiguration('coc.preferences.diagnostic'); + let config = workspace_1.default.getConfiguration('diagnostic'); + function getConfig(key, defaultValue) { + return preferences.get(key, config.get(key, defaultValue)); } - else if (this.ifValue && this.elseValue) { - value += `:?${this.ifValue}:${this.elseValue}`; + let messageTarget = getConfig('messageTarget', 'float'); + if (messageTarget == 'float' && !workspace_1.default.env.floating && !workspace_1.default.env.textprop) { + messageTarget = 'echo'; } - else if (this.ifValue) { - value += `:+${this.ifValue}`; + this.config = { + messageTarget, + srcId: workspace_1.default.createNameSpace('coc-diagnostic') || 1000, + virtualTextSrcId: workspace_1.default.createNameSpace('diagnostic-virtualText'), + checkCurrentLine: getConfig('checkCurrentLine', false), + enableSign: getConfig('enableSign', true), + enableHighlightLineNumber: getConfig('enableHighlightLineNumber', true), + maxWindowHeight: getConfig('maxWindowHeight', 10), + maxWindowWidth: getConfig('maxWindowWidth', 80), + enableMessage: getConfig('enableMessage', 'always'), + joinMessageLines: getConfig('joinMessageLines', false), + messageDelay: getConfig('messageDelay', 250), + virtualText: getConfig('virtualText', false), + virtualTextPrefix: getConfig('virtualTextPrefix', " "), + virtualTextLineSeparator: getConfig('virtualTextLineSeparator', " \\ "), + virtualTextLines: getConfig('virtualTextLines', 3), + displayByAle: getConfig('displayByAle', false), + level: util_2.severityLevel(getConfig('level', 'hint')), + locationlist: getConfig('locationlist', true), + signOffset: getConfig('signOffset', 1000), + errorSign: getConfig('errorSign', '>>'), + warningSign: getConfig('warningSign', '>>'), + infoSign: getConfig('infoSign', '>>'), + hintSign: getConfig('hintSign', '>>'), + refreshAfterSave: getConfig('refreshAfterSave', false), + refreshOnInsertMode: getConfig('refreshOnInsertMode', false), + filetypeMap: getConfig('filetypeMap', {}), + format: getConfig('format', '[%source%code] [%severity] %message') + }; + this.enabled = getConfig('enable', true); + if (this.config.displayByAle) { + this.enabled = false; } - else if (this.elseValue) { - value += `:-${this.elseValue}`; + if (event) { + for (let severity of ['error', 'info', 'warning', 'hint']) { + let key = `diagnostic.${severity}Sign`; + if (event.affectsConfiguration(key)) { + let text = config.get(`${severity}Sign`, '>>'); + let name = severity[0].toUpperCase() + severity.slice(1); + this.nvim.command(`sign define Coc${name} text=${text} linehl=Coc${name}Line texthl=Coc${name}Sign`, true); + } + } } - value += '}'; - return value; } - clone() { - let ret = new FormatString(this.index, this.shorthandName, this.ifValue, this.elseValue); - return ret; + getCollections(uri) { + return this.collections.filter(c => c.has(uri)); } -} -exports.FormatString = FormatString; -class Variable extends TransformableMarker { - constructor(name) { - super(); - this.name = name; + shouldValidate(doc) { + return doc != null && doc.buftype == ''; } - resolve(resolver) { - let value = resolver.resolve(this); - if (value && value.indexOf('\n') !== -1) { - // get indent of previous Text child - let { children } = this.parent; - let idx = children.indexOf(this); - let previous = children[idx - 1]; - if (previous && previous instanceof Text) { - let ms = previous.value.match(/\n([ \t]*)$/); - if (ms) { - let lines = value.split('\n'); - let indents = lines.filter(s => s.length > 0).map(s => s.match(/^\s*/)[0]); - let minIndent = indents.length == 0 ? '' : - indents.reduce((p, c) => p.length < c.length ? p : c); - let newLines = lines.map((s, i) => { - return i == 0 || s.length == 0 || !s.startsWith(minIndent) ? s : - ms[1] + s.slice(minIndent.length); - }); - value = newLines.join('\n'); - } + refreshBuffer(uri) { + let { insertMode } = workspace_1.default; + if (insertMode && !this.config.refreshOnInsertMode) + return; + let buf = this.buffers.find(buf => buf.uri == uri); + if (!buf) + return; + let { displayByAle } = this.config; + if (!displayByAle) { + let diagnostics = this.getDiagnostics(uri); + if (this.enabled) { + buf.refresh(diagnostics); + return true; } } - if (this.transform) { - value = this.transform.resolve(value || ''); - } - if (value !== undefined) { - this._children = [new Text(value)]; - return true; + else { + let { nvim } = this; + nvim.pauseNotification(); + for (let collection of this.collections) { + let diagnostics = collection.get(uri); + const { level } = this.config; + if (level) { + diagnostics = diagnostics.filter(o => o.severity && o.severity <= level); + } + let aleItems = diagnostics.map(o => { + let { range } = o; + return { + text: o.message, + code: o.code, + lnum: range.start.line + 1, + col: range.start.character + 1, + end_lnum: range.end.line + 1, + end_col: range.end.character, + type: util_2.getSeverityType(o.severity) + }; + }); + nvim.call('ale#other_source#ShowResults', [buf.bufnr, collection.name, aleItems], true); + } + nvim.resumeNotification(false, true).logError(); } return false; } - toTextmateString() { - let transformString = ''; - if (this.transform) { - transformString = this.transform.toTextmateString(); - } - if (this.children.length === 0) { - return `\${${this.name}${transformString}}`; - } - else { - return `\${${this.name}:${this.children.map(child => child.toTextmateString()).join('')}${transformString}}`; - } +} +exports.DiagnosticManager = DiagnosticManager; +exports.default = new DiagnosticManager(); +//# sourceMappingURL=manager.js.map + +/***/ }), +/* 249 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const tslib_1 = __webpack_require__(3); +const vscode_languageserver_protocol_1 = __webpack_require__(150); +const events_1 = tslib_1.__importDefault(__webpack_require__(149)); +const manager_1 = tslib_1.__importDefault(__webpack_require__(250)); +const util_1 = __webpack_require__(177); +const object_1 = __webpack_require__(193); +const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); +const floatBuffer_1 = tslib_1.__importDefault(__webpack_require__(344)); +const debounce_1 = tslib_1.__importDefault(__webpack_require__(179)); +const popup_1 = tslib_1.__importDefault(__webpack_require__(398)); +const array_1 = __webpack_require__(215); +const logger = __webpack_require__(2)('model-float'); +// factory class for floating window +class FloatFactory { + constructor(nvim, env, preferTop = false, maxHeight = 999, maxWidth, autoHide = true) { + this.nvim = nvim; + this.env = env; + this.preferTop = preferTop; + this.maxHeight = maxHeight; + this.maxWidth = maxWidth; + this.autoHide = autoHide; + this.disposables = []; + this.alignTop = false; + this.pumAlignTop = false; + this.createTs = 0; + this.cursor = [0, 0]; + this.shown = false; + if (!workspace_1.default.floatSupported) + return; + this.maxWidth = Math.min(maxWidth || 80, this.columns - 10); + events_1.default.on('BufEnter', bufnr => { + if (this.buffer && bufnr == this.buffer.id) + return; + if (bufnr == this.targetBufnr) + return; + this.close(); + }, null, this.disposables); + events_1.default.on('InsertLeave', bufnr => { + if (this.buffer && bufnr == this.buffer.id) + return; + if (manager_1.default.isActived(bufnr)) + return; + this.close(); + }, null, this.disposables); + events_1.default.on('MenuPopupChanged', async (ev, cursorline) => { + let pumAlignTop = this.pumAlignTop = cursorline > ev.row; + if (pumAlignTop == this.alignTop) { + this.close(); + } + }, null, this.disposables); + events_1.default.on('CursorMoved', debounce_1.default((bufnr, cursor) => { + if (Date.now() - this.createTs < 100) + return; + this.onCursorMoved(false, bufnr, cursor); + }, 100), null, this.disposables); + events_1.default.on('CursorMovedI', this.onCursorMoved.bind(this, true), null, this.disposables); } - clone() { - const ret = new Variable(this.name); - if (this.transform) { - ret.transform = this.transform.clone(); + onCursorMoved(insertMode, bufnr, cursor) { + if (!this.window || this.buffer && bufnr == this.buffer.id) + return; + if (bufnr == this.targetBufnr && object_1.equals(cursor, this.cursor)) + return; + if (this.autoHide) { + this.close(); + return; } - ret._children = this.children.map(child => child.clone()); - return ret; - } -} -exports.Variable = Variable; -function walk(marker, visitor) { - const stack = [...marker]; - while (stack.length > 0) { - const marker = stack.shift(); - const recurse = visitor(marker); - if (!recurse) { - break; + if (!insertMode || bufnr != this.targetBufnr || (this.cursor && cursor[0] != this.cursor[0])) { + this.close(); + return; } - stack.unshift(...marker.children); } -} -class TextmateSnippet extends Marker { - get placeholderInfo() { - if (!this._placeholders) { - // fill in placeholders - let all = []; - let last; - this.walk(candidate => { - if (candidate instanceof Placeholder) { - all.push(candidate); - last = !last || last.index < candidate.index ? candidate : last; + async checkFloatBuffer() { + let { floatBuffer, nvim, window } = this; + if (this.env.textprop) { + let valid = await this.activated(); + if (!valid) + window = null; + if (!window) { + this.popup = await popup_1.default(nvim, [''], { + padding: [0, 1, 0, 1], + highlight: 'CocFloating', + tab: -1, + }); + let win = this.window = nvim.createWindow(this.popup.id); + nvim.pauseNotification(); + win.setVar('float', 1, true); + win.setOption('linebreak', true, true); + if (workspace_1.default.isVim && parseInt(workspace_1.default.env.version, 10) >= 8012281) { + win.setOption('showbreak', 'NONE', true); } - return true; - }); - this._placeholders = { all, last }; + win.setOption('conceallevel', 2, true); + await nvim.resumeNotification(); + } + let buffer = this.nvim.createBuffer(this.popup.bufferId); + this.floatBuffer = new floatBuffer_1.default(nvim, buffer, nvim.createWindow(this.popup.id)); + } + else { + if (floatBuffer) { + let valid = await floatBuffer.valid; + if (valid) + return; + } + let buf = await this.nvim.createNewBuffer(false, true); + await buf.setOption('buftype', 'nofile'); + await buf.setOption('bufhidden', 'hide'); + this.floatBuffer = new floatBuffer_1.default(this.nvim, buf); } - return this._placeholders; } - get placeholders() { - const { all } = this.placeholderInfo; - return all; + get columns() { + return this.env.columns; } - get maxIndexNumber() { - let { placeholders } = this; - return placeholders.reduce((curr, p) => { - return Math.max(curr, p.index); - }, 0); + get lines() { + return this.env.lines - this.env.cmdheight - 1; } - get minIndexNumber() { - let { placeholders } = this; - let nums = placeholders.map(p => p.index); - nums.sort((a, b) => a - b); - if (nums.length > 1 && nums[0] == 0) - return nums[1]; - return nums[0] || 0; + async getBoundings(docs, offsetX = 0) { + let { nvim, preferTop } = this; + let { columns, lines } = this; + let alignTop = false; + let [row, col] = await nvim.call('coc#util#win_position'); + let maxWidth = this.maxWidth; + let height = this.floatBuffer.getHeight(docs, maxWidth); + height = Math.min(height, this.maxHeight); + if (!preferTop) { + if (lines - row < height && row > height) { + alignTop = true; + } + } + else { + if (row >= height || row >= lines - row) { + alignTop = true; + } + } + if (alignTop) + docs.reverse(); + await this.floatBuffer.setDocuments(docs, maxWidth); + let { width } = this.floatBuffer; + // Ensure the floating window isn't tiny if the cursor is on the right: + // increase the offset to accommodate some minimum width. + // If we have offsetX, precise positioning is intended, force exact width. + let minWidth = offsetX ? width : Math.min(width, 50, maxWidth); + offsetX = Math.min(col - 1, offsetX); + if (col - offsetX + minWidth > columns) { + offsetX = col - offsetX + minWidth - columns; + } + this.alignTop = alignTop; + return { + height: alignTop ? Math.max(1, Math.min(row, height)) : Math.max(1, Math.min(height, (lines - row))), + width: Math.min(columns, width), + row: alignTop ? -height : 1, + col: offsetX == 0 ? 0 : -offsetX, + relative: 'cursor' + }; } - insertSnippet(snippet, id, range) { - let placeholder = this.placeholders[id]; - if (!placeholder) + async create(docs, allowSelection = false, offsetX = 0) { + if (!workspace_1.default.floatSupported) { + logger.error('Floating window & textprop not supported!'); return; - let { index } = placeholder; - const document = vscode_languageserver_protocol_1.TextDocument.create('untitled:/1', 'snippet', 0, placeholder.toString()); - snippet = vscode_languageserver_protocol_1.TextDocument.applyEdits(document, [{ range, newText: snippet.replace(/\$0$/, '') }]); - let nested = new SnippetParser().parse(snippet, false); - let maxIndexAdded = nested.maxIndexNumber; - let totalAdd = maxIndexAdded + -1; - for (let p of nested.placeholders) { - if (p.isFinalTabstop) { - p.index = maxIndexAdded + index + 1; + } + let shown = await this.createPopup(docs, allowSelection, offsetX); + if (!shown) + this.close(false); + } + async createPopup(docs, allowSelection = false, offsetX = 0) { + if (this.tokenSource) { + this.tokenSource.cancel(); + } + if (docs.length == 0) + return false; + this.createTs = Date.now(); + this.targetBufnr = workspace_1.default.bufnr; + let tokenSource = this.tokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource(); + let token = tokenSource.token; + await this.checkFloatBuffer(); + let config = await this.getBoundings(docs, offsetX); + let [mode, line, col, visible] = await this.nvim.eval('[mode(),line("."),col("."),pumvisible()]'); + this.cursor = [line, col]; + if (visible && this.alignTop == this.pumAlignTop) + return false; + if (!config || token.isCancellationRequested) + return false; + if (!this.checkMode(mode, allowSelection)) + return false; + let { nvim, alignTop } = this; + if (mode == 's') + await nvim.call('feedkeys', ['\x1b', 'in']); + // helps to fix undo issue, don't know why. + if (workspace_1.default.isNvim && mode.startsWith('i')) + await nvim.eval('feedkeys("\\u", "n")'); + let reuse = false; + if (workspace_1.default.isNvim) { + reuse = this.window && await this.window.valid; + if (!reuse) + this.window = await nvim.openFloatWindow(this.buffer, false, config); + } + if (token.isCancellationRequested) + return false; + nvim.pauseNotification(); + if (workspace_1.default.isNvim) { + if (!reuse) { + nvim.command(`noa call win_gotoid(${this.window.id})`, true); + this.window.setVar('float', 1, true); + nvim.command(`setl nospell nolist wrap linebreak foldcolumn=1 showbreak=`, true); + nvim.command(`setl nonumber norelativenumber nocursorline nocursorcolumn colorcolumn=`, true); + nvim.command(`setl signcolumn=no conceallevel=2 concealcursor=n`, true); + nvim.command(`setl winhl=Normal:CocFloating,NormalNC:CocFloating,FoldColumn:CocFloating`, true); + nvim.call('coc#util#do_autocmd', ['CocOpenFloat'], true); } else { - p.index = p.index + index; + this.window.setConfig(config, true); + nvim.command(`noa call win_gotoid(${this.window.id})`, true); } + this.floatBuffer.setLines(); + nvim.command(`normal! ${alignTop ? 'G' : 'gg'}0`, true); + nvim.command('noa wincmd p', true); } - this.walk(m => { - if (m instanceof Placeholder && m.index > index) { - m.index = m.index + totalAdd + 1; + else { + let filetypes = array_1.distinct(docs.map(d => d.filetype)); + if (filetypes.length == 1) { + this.popup.setFiletype(filetypes[0]); } - return true; - }); - this.replace(placeholder, nested.children); - return index + 1; + this.popup.move({ + line: cursorPostion(config.row), + col: cursorPostion(config.col), + minwidth: config.width - 2, + minheight: config.height, + maxwidth: config.width - 2, + maxheight: this.maxHeight, + firstline: alignTop ? -1 : 1 + }); + this.floatBuffer.setLines(); + nvim.command('redraw', true); + } + let [, err] = await nvim.resumeNotification(); + if (err) { + workspace_1.default.showMessage(`Error on ${err[0]}: ${err[1]} - ${err[2]}`, 'error'); + return false; + } + if (mode == 's') + await manager_1.default.selectCurrentPlaceholder(false); + return true; } - updatePlaceholder(id, val) { - const placeholder = this.placeholders[id]; - for (let p of this.placeholders) { - if (p.index == placeholder.index) { - let child = p.children[0]; - let newText = p.transform ? p.transform.resolve(val) : val; - if (child) { - p.setOnlyChild(new Text(newText)); - } - else { - p.appendChild(new Text(newText)); - } - } + checkMode(mode, allowSelection) { + if (mode == 's' && allowSelection) { + return true; } - this._placeholders = undefined; + return ['i', 'n', 'ic'].indexOf(mode) != -1; } /** - * newText after update with value + * Close float window */ - getPlaceholderText(id, value) { - const placeholder = this.placeholders[id]; - if (!placeholder) - return value; - return placeholder.transform ? placeholder.transform.resolve(value) : value; - } - offset(marker) { - let pos = 0; - let found = false; - this.walk(candidate => { - if (candidate === marker) { - found = true; - return false; + close(cancel = true) { + if (cancel && this.tokenSource) { + if (this.tokenSource) { + this.tokenSource.cancel(); + this.tokenSource = null; } - pos += candidate.len(); - return true; - }); - if (!found) { - return -1; } - return pos; - } - fullLen(marker) { - let ret = 0; - walk([marker], marker => { - ret += marker.len(); - return true; - }); - return ret; - } - enclosingPlaceholders(placeholder) { - let ret = []; - let { parent } = placeholder; - while (parent) { - if (parent instanceof Placeholder) { - ret.push(parent); - } - parent = parent.parent; + let { window, popup } = this; + this.shown = false; + if (this.env.textprop) { + if (popup) + popup.dispose(); + } + else if (window) { + window.close(true, true); } - return ret; - } - resolveVariables(resolver) { - this.walk(candidate => { - if (candidate instanceof Variable) { - if (candidate.resolve(resolver)) { - this._placeholders = undefined; - } - } - return true; - }); - return this; - } - appendChild(child) { - this._placeholders = undefined; - return super.appendChild(child); - } - replace(child, others) { - this._placeholders = undefined; - return super.replace(child, others); } - toTextmateString() { - return this.children.reduce((prev, cur) => prev + cur.toTextmateString(), ''); + dispose() { + if (this.tokenSource) { + this.tokenSource.cancel(); + } + util_1.disposeAll(this.disposables); } - clone() { - let ret = new TextmateSnippet(); - this._children = this.children.map(child => child.clone()); - return ret; + get buffer() { + return this.floatBuffer ? this.floatBuffer.buffer : null; } - walk(visitor) { - walk(this.children, visitor); + async activated() { + if (this.env.textprop) { + if (!this.popup) + return false; + return await this.popup.visible(); + } + if (!this.window) + return false; + let valid = await this.window.valid; + return valid; } } -exports.TextmateSnippet = TextmateSnippet; -class SnippetParser { +exports.default = FloatFactory; +function cursorPostion(n) { + if (n == 0) + return 'cursor'; + if (n < 0) + return `cursor${n}`; + return `cursor+${n}`; +} +//# sourceMappingURL=floatFactory.js.map + +/***/ }), +/* 250 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const tslib_1 = __webpack_require__(3); +const events_1 = tslib_1.__importDefault(__webpack_require__(149)); +const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); +const Snippets = tslib_1.__importStar(__webpack_require__(251)); +const parser_1 = __webpack_require__(251); +const session_1 = __webpack_require__(252); +const variableResolve_1 = __webpack_require__(400); +const logger = __webpack_require__(2)('snippets-manager'); +class SnippetManager { constructor() { - this._scanner = new Scanner(); - } - static escape(value) { - return value.replace(/\$|}|\\/g, '\\$&'); - } - text(value) { - return this.parse(value).toString(); - } - parse(value, insertFinalTabstop) { - this._scanner.text(value); - this._token = this._scanner.next(); - const snippet = new TextmateSnippet(); - while (this._parse(snippet)) { - // nothing - } - // fill in values for placeholders. the first placeholder of an index - // that has a value defines the value for all placeholders with that index - const placeholderDefaultValues = new Map(); - const incompletePlaceholders = []; - snippet.walk(marker => { - if (marker instanceof Placeholder) { - if (marker.isFinalTabstop) { - placeholderDefaultValues.set(0, undefined); - } - else if (!placeholderDefaultValues.has(marker.index) && marker.children.length > 0) { - placeholderDefaultValues.set(marker.index, marker.children); - } - else { - incompletePlaceholders.push(marker); - } - } - return true; - }); - for (const placeholder of incompletePlaceholders) { - if (placeholderDefaultValues.has(placeholder.index)) { - const clone = new Placeholder(placeholder.index); - clone.transform = placeholder.transform; - for (const child of placeholderDefaultValues.get(placeholder.index)) { - let marker = child.clone(); - if (clone.transform) { - if (marker instanceof Text) { - marker = new Text(clone.transform.resolve(marker.value)); - } - else { - for (let child of marker.children) { - if (child instanceof Text) { - marker.replace(child, [new Text(clone.transform.resolve(child.value))]); - break; - } - } - } - } - clone.appendChild(marker); - } - snippet.replace(placeholder, [clone]); + this.sessionMap = new Map(); + this.disposables = []; + // tslint:disable-next-line:no-floating-promises + workspace_1.default.ready.then(() => { + let config = workspace_1.default.getConfiguration('coc.preferences'); + this.statusItem = workspace_1.default.createStatusBarItem(0); + this.statusItem.text = config.get('snippetStatusText', 'SNIP'); + }); + workspace_1.default.onDidChangeTextDocument(async (e) => { + let { uri } = e.textDocument; + let doc = workspace_1.default.getDocument(uri); + if (!doc) + return; + let session = this.getSession(doc.bufnr); + if (session && session.isActive) { + await session.synchronizeUpdatedPlaceholders(e.contentChanges[0]); + } + }, null, this.disposables); + workspace_1.default.onDidCloseTextDocument(textDocument => { + let doc = workspace_1.default.getDocument(textDocument.uri); + if (!doc) + return; + let session = this.getSession(doc.bufnr); + if (session) + session.deactivate(); + }, null, this.disposables); + events_1.default.on('BufEnter', async (bufnr) => { + let session = this.getSession(bufnr); + if (!this.statusItem) + return; + if (session && session.isActive) { + this.statusItem.show(); + } + else { + this.statusItem.hide(); } + }, null, this.disposables); + events_1.default.on('InsertEnter', async () => { + let { session } = this; + if (!session) + return; + await session.checkPosition(); + }, null, this.disposables); + } + /** + * Insert snippet at current cursor position + */ + async insertSnippet(snippet, select = true, range) { + let { nvim } = workspace_1.default; + let bufnr = await nvim.call('bufnr', '%'); + let session = this.getSession(bufnr); + if (!session) { + session = new session_1.SnippetSession(workspace_1.default.nvim, bufnr); + this.sessionMap.set(bufnr, session); + session.onCancel(() => { + this.sessionMap.delete(bufnr); + if (workspace_1.default.bufnr == bufnr) { + this.statusItem.hide(); + } + }); } - if (!placeholderDefaultValues.has(0) && insertFinalTabstop) { - // the snippet uses placeholders but has no - // final tabstop defined -> insert at the end - snippet.appendChild(new Placeholder(0)); + let isActive = await session.start(snippet, select, range); + if (isActive) { + this.statusItem.show(); } - return snippet; + else if (session) { + session.deactivate(); + } + nvim.command('silent! unlet g:coc_last_placeholder g:coc_selected_text', true); + return isActive; } - _accept(type, value) { - if (type === undefined || this._token.type === type) { - let ret = !value ? true : this._scanner.tokenText(this._token); - this._token = this._scanner.next(); - return ret; + isPlainText(text) { + let snippet = (new parser_1.SnippetParser()).parse(text, true); + if (snippet.placeholders.every(p => p.isFinalTabstop == true && p.toString() == '')) { + return true; } return false; } - _backTo(token) { - this._scanner.pos = token.pos + token.len; - this._token = token; - return false; + async selectCurrentPlaceholder(triggerAutocmd = true) { + let { session } = this; + if (session) + return await session.selectCurrentPlaceholder(triggerAutocmd); } - _until(type) { - if (this._token.type === 14 /* EOF */) { - return false; - } - let start = this._token; - while (this._token.type !== type) { - this._token = this._scanner.next(); - if (this._token.type === 14 /* EOF */) { - return false; - } - } - let value = this._scanner.value.substring(start.pos, this._token.pos); - this._token = this._scanner.next(); - return value; + async nextPlaceholder() { + let { session } = this; + if (session) + return await session.nextPlaceholder(); + workspace_1.default.nvim.call('coc#snippet#disable', [], true); + this.statusItem.hide(); } - _parse(marker) { - return this._parseEscaped(marker) - || this._parseTabstopOrVariableName(marker) - || this._parseComplexPlaceholder(marker) - || this._parseComplexVariable(marker) - || this._parseAnything(marker); + async previousPlaceholder() { + let { session } = this; + if (session) + return await session.previousPlaceholder(); + workspace_1.default.nvim.call('coc#snippet#disable', [], true); + this.statusItem.hide(); } - // \$, \\, \} -> just text - _parseEscaped(marker) { - let value; - if (value = this._accept(5 /* Backslash */, true)) { // tslint:disable-line - // saw a backslash, append escaped token or that backslash - value = this._accept(0 /* Dollar */, true) - || this._accept(4 /* CurlyClose */, true) - || this._accept(5 /* Backslash */, true) - || value; - marker.appendChild(new Text(value)); + cancel() { + let session = this.getSession(workspace_1.default.bufnr); + if (session) + return session.deactivate(); + workspace_1.default.nvim.call('coc#snippet#disable', [], true); + if (this.statusItem) + this.statusItem.hide(); + } + get session() { + let session = this.getSession(workspace_1.default.bufnr); + return session && session.isActive ? session : null; + } + isActived(bufnr) { + let session = this.getSession(bufnr); + return session && session.isActive; + } + jumpable() { + let { session } = this; + if (!session) + return false; + let placeholder = session.placeholder; + if (placeholder && !placeholder.isFinalTabstop) { return true; } return false; } - // $foo -> variable, $1 -> tabstop - _parseTabstopOrVariableName(parent) { - let value; - const token = this._token; - const match = this._accept(0 /* Dollar */) - && (value = this._accept(9 /* VariableName */, true) || this._accept(8 /* Int */, true)); - if (!match) { - return this._backTo(token); + getSession(bufnr) { + return this.sessionMap.get(bufnr); + } + async resolveSnippet(body) { + let parser = new Snippets.SnippetParser(); + const snippet = parser.parse(body, true); + const resolver = new variableResolve_1.SnippetVariableResolver(); + snippet.resolveVariables(resolver); + return snippet; + } + dispose() { + this.cancel(); + for (let d of this.disposables) { + d.dispose(); } - parent.appendChild(/^\d+$/.test(value) - ? new Placeholder(Number(value)) - : new Variable(value)); - return true; } - // ${1:}, ${1} -> placeholder - _parseComplexPlaceholder(parent) { - let index; - const token = this._token; - const match = this._accept(0 /* Dollar */) - && this._accept(3 /* CurlyOpen */) - && (index = this._accept(8 /* Int */, true)); - if (!match) { - return this._backTo(token); +} +exports.SnippetManager = SnippetManager; +exports.default = new SnippetManager(); +//# sourceMappingURL=manager.js.map + +/***/ }), +/* 251 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +const vscode_languageserver_protocol_1 = __webpack_require__(150); +const logger = __webpack_require__(2)('snippets-parser'); +class Scanner { + constructor() { + this.text(''); + } + static isDigitCharacter(ch) { + return ch >= 48 /* Digit0 */ && ch <= 57 /* Digit9 */; + } + static isVariableCharacter(ch) { + return ch === 95 /* Underline */ + || (ch >= 97 /* a */ && ch <= 122 /* z */) + || (ch >= 65 /* A */ && ch <= 90 /* Z */); + } + text(value) { + this.value = value; + this.pos = 0; + } + tokenText(token) { + return this.value.substr(token.pos, token.len); + } + next() { + if (this.pos >= this.value.length) { + return { type: 14 /* EOF */, pos: this.pos, len: 0 }; } - const placeholder = new Placeholder(Number(index)); - if (this._accept(1 /* Colon */)) { - // ${1:} - while (true) { - // ...} -> done - if (this._accept(4 /* CurlyClose */)) { - parent.appendChild(placeholder); - return true; - } - if (this._parse(placeholder)) { - continue; - } - // fallback - parent.appendChild(new Text('${' + index + ':')); - placeholder.children.forEach(parent.appendChild, parent); - return true; - } + let pos = this.pos; + let len = 0; + let ch = this.value.charCodeAt(pos); + let type; + // static types + type = Scanner._table[ch]; + if (typeof type === 'number') { + this.pos += 1; + return { type, pos, len: 1 }; } - else if (placeholder.index > 0 && this._accept(7 /* Pipe */)) { - // ${1|one,two,three|} - const choice = new Choice(); - while (true) { - if (this._parseChoiceElement(choice)) { - if (this._accept(2 /* Comma */)) { - // opt, -> more - continue; - } - if (this._accept(7 /* Pipe */)) { - placeholder.appendChild(choice); - if (this._accept(4 /* CurlyClose */)) { - // ..|} -> done - parent.appendChild(placeholder); - return true; - } - } - } - this._backTo(token); - return false; - } + // number + if (Scanner.isDigitCharacter(ch)) { + type = 8 /* Int */; + do { + len += 1; + ch = this.value.charCodeAt(pos + len); + } while (Scanner.isDigitCharacter(ch)); + this.pos += len; + return { type, pos, len }; } - else if (this._accept(6 /* Forwardslash */)) { - // ${1///} - if (this._parseTransform(placeholder)) { - parent.appendChild(placeholder); - return true; - } - this._backTo(token); - return false; + // variable name + if (Scanner.isVariableCharacter(ch)) { + type = 9 /* VariableName */; + do { + ch = this.value.charCodeAt(pos + (++len)); + } while (Scanner.isVariableCharacter(ch) || Scanner.isDigitCharacter(ch)); + this.pos += len; + return { type, pos, len }; } - else if (this._accept(4 /* CurlyClose */)) { - // ${1} - parent.appendChild(placeholder); - return true; + // format + type = 10 /* Format */; + do { + len += 1; + ch = this.value.charCodeAt(pos + len); + } while (!isNaN(ch) + && typeof Scanner._table[ch] === 'undefined' // not static token + && !Scanner.isDigitCharacter(ch) // not number + && !Scanner.isVariableCharacter(ch) // not variable + ); + this.pos += len; + return { type, pos, len }; + } +} +exports.Scanner = Scanner; +Scanner._table = { + [36 /* DollarSign */]: 0 /* Dollar */, + [58 /* Colon */]: 1 /* Colon */, + [44 /* Comma */]: 2 /* Comma */, + [123 /* OpenCurlyBrace */]: 3 /* CurlyOpen */, + [125 /* CloseCurlyBrace */]: 4 /* CurlyClose */, + [92 /* Backslash */]: 5 /* Backslash */, + [47 /* Slash */]: 6 /* Forwardslash */, + [124 /* Pipe */]: 7 /* Pipe */, + [43 /* Plus */]: 11 /* Plus */, + [45 /* Dash */]: 12 /* Dash */, + [63 /* QuestionMark */]: 13 /* QuestionMark */, +}; +class Marker { + constructor() { + this._children = []; + } + appendChild(child) { + if (child instanceof Text && this._children[this._children.length - 1] instanceof Text) { + // this and previous child are text -> merge them + this._children[this._children.length - 1].value += child.value; } else { - // ${1 <- missing curly or colon - return this._backTo(token); + // normal adoption of child + child.parent = this; + this._children.push(child); } + return this; } - _parseChoiceElement(parent) { - const token = this._token; - const values = []; - while (true) { - if (this._token.type === 2 /* Comma */ || this._token.type === 7 /* Pipe */) { - break; - } - let value; - if (value = this._accept(5 /* Backslash */, true)) { // tslint:disable-line - // \, \|, or \\ - value = this._accept(2 /* Comma */, true) - || this._accept(7 /* Pipe */, true) - || this._accept(5 /* Backslash */, true) - || value; + setOnlyChild(child) { + child.parent = this; + this._children = [child]; + } + replace(child, others) { + const { parent } = child; + const idx = parent.children.indexOf(child); + const newChildren = parent.children.slice(0); + newChildren.splice(idx, 1, ...others); + parent._children = newChildren; + (function _fixParent(children, parent) { + for (const child of children) { + child.parent = parent; + _fixParent(child.children, child); } - else { - value = this._accept(undefined, true); + })(others, parent); + } + get children() { + return this._children; + } + get snippet() { + let candidate = this; + while (true) { + if (!candidate) { + return undefined; } - if (!value) { - // EOF - this._backTo(token); - return false; + if (candidate instanceof TextmateSnippet) { + return candidate; } - values.push(value); - } - if (values.length === 0) { - this._backTo(token); - return false; + candidate = candidate.parent; } - parent.appendChild(new Text(values.join(''))); - return true; } - // ${foo:}, ${foo} -> variable - _parseComplexVariable(parent) { - let name; - const token = this._token; - const match = this._accept(0 /* Dollar */) - && this._accept(3 /* CurlyOpen */) - && (name = this._accept(9 /* VariableName */, true)); - if (!match) { - return this._backTo(token); + toString() { + return this.children.reduce((prev, cur) => prev + cur.toString(), ''); + } + len() { + return 0; + } + get next() { + let { parent } = this; + let { children } = parent; + let idx = children.indexOf(this); + return children[idx + 1]; + } +} +exports.Marker = Marker; +class Text extends Marker { + constructor(value) { + super(); + this.value = value; + } + static escape(value) { + return value.replace(/\$|}|\\/g, '\\$&'); + } + toString() { + return this.value; + } + toTextmateString() { + return Text.escape(this.value); + } + len() { + return this.value.length; + } + clone() { + return new Text(this.value); + } +} +exports.Text = Text; +class TransformableMarker extends Marker { +} +exports.TransformableMarker = TransformableMarker; +class Placeholder extends TransformableMarker { + constructor(index) { + super(); + this.index = index; + } + static compareByIndex(a, b) { + if (a.index === b.index) { + return 0; } - const variable = new Variable(name); - if (this._accept(1 /* Colon */)) { - // ${foo:} - while (true) { - // ...} -> done - if (this._accept(4 /* CurlyClose */)) { - parent.appendChild(variable); - return true; - } - if (this._parse(variable)) { - continue; - } - // fallback - parent.appendChild(new Text('${' + name + ':')); - variable.children.forEach(parent.appendChild, parent); - return true; - } + else if (a.isFinalTabstop) { + return 1; } - else if (this._accept(6 /* Forwardslash */)) { - // ${foo///} - if (this._parseTransform(variable)) { - parent.appendChild(variable); - return true; - } - this._backTo(token); - return false; + else if (b.isFinalTabstop) { + return -1; } - else if (this._accept(4 /* CurlyClose */)) { - // ${foo} - parent.appendChild(variable); - return true; + else if (a.index < b.index) { + return -1; + } + else if (a.index > b.index) { + return 1; } else { - // ${foo <- missing curly or colon - return this._backTo(token); + return 0; } } - _parseTransform(parent) { - // ...//} - let transform = new Transform(); - let regexValue = ''; - let regexOptions = ''; - // (1) /regex - while (true) { - if (this._accept(6 /* Forwardslash */)) { - break; - } - let escaped; - if (escaped = this._accept(5 /* Backslash */, true)) { // tslint:disable-line - escaped = this._accept(6 /* Forwardslash */, true) || escaped; - regexValue += escaped; - continue; - } - if (this._token.type !== 14 /* EOF */) { - regexValue += this._accept(undefined, true); - continue; - } - return false; + get isFinalTabstop() { + return this.index === 0; + } + get choice() { + return this._children.length === 1 && this._children[0] instanceof Choice + ? this._children[0] + : undefined; + } + toTextmateString() { + let transformString = ''; + if (this.transform) { + transformString = this.transform.toTextmateString(); } - // (2) /format - while (true) { - if (this._accept(6 /* Forwardslash */)) { - break; - } - let escaped; - if (escaped = this._accept(5 /* Backslash */, true)) { // tslint:disable-line - escaped = this._accept(6 /* Forwardslash */, true) || escaped; - transform.appendChild(new Text(escaped)); - continue; - } - if (this._parseFormatString(transform) || this._parseAnything(transform)) { - let text = transform.children[0]; - if (text && text.value && text.value.indexOf('\\n') !== -1) { - text.value = text.value.replace(/\\n/g, '\n'); - } - continue; - } - return false; + if (this.children.length === 0 && !this.transform) { + return `\$${this.index}`; } - // (3) /option - while (true) { - if (this._accept(4 /* CurlyClose */)) { - break; - } - if (this._token.type !== 14 /* EOF */) { - regexOptions += this._accept(undefined, true); - continue; - } - return false; + else if (this.children.length === 0) { + return `\${${this.index}${transformString}}`; } - try { - transform.regexp = new RegExp(regexValue, regexOptions); + else if (this.choice) { + return `\${${this.index}|${this.choice.toTextmateString()}|${transformString}}`; } - catch (e) { - // invalid regexp - return false; + else { + return `\${${this.index}:${this.children.map(child => child.toTextmateString()).join('')}${transformString}}`; } - parent.transform = transform; - return true; } - _parseFormatString(parent) { - const token = this._token; - if (!this._accept(0 /* Dollar */)) { - return false; - } - let complex = false; - if (this._accept(3 /* CurlyOpen */)) { - complex = true; - } - let index = this._accept(8 /* Int */, true); - if (!index) { - this._backTo(token); - return false; + clone() { + let ret = new Placeholder(this.index); + if (this.transform) { + ret.transform = this.transform.clone(); } - else if (!complex) { - // $1 - parent.appendChild(new FormatString(Number(index))); - return true; + ret._children = this.children.map(child => child.clone()); + return ret; + } +} +exports.Placeholder = Placeholder; +class Choice extends Marker { + constructor() { + super(...arguments); + this.options = []; + } + appendChild(marker) { + if (marker instanceof Text) { + marker.parent = this; + this.options.push(marker); } - else if (this._accept(4 /* CurlyClose */)) { - // ${1} - parent.appendChild(new FormatString(Number(index))); - return true; + return this; + } + toString() { + return this.options[0].value; + } + toTextmateString() { + return this.options + .map(option => option.value.replace(/\||,/g, '\\$&')) + .join(','); + } + len() { + return this.options[0].len(); + } + clone() { + let ret = new Choice(); + for (let opt of this.options) { + ret.appendChild(opt); } - else if (!this._accept(1 /* Colon */)) { - this._backTo(token); - return false; + return ret; + } +} +exports.Choice = Choice; +class Transform extends Marker { + resolve(value) { + let didMatch = false; + let ret = value.replace(this.regexp, (...args) => { + didMatch = true; + return this._replace(args.slice(0, -2)); + }); + // when the regex didn't match and when the transform has + // else branches, then run those + if (!didMatch && this._children.some(child => child instanceof FormatString && Boolean(child.elseValue))) { + ret = this._replace([]); } - if (this._accept(6 /* Forwardslash */)) { - // ${1:/upcase} - let shorthand = this._accept(9 /* VariableName */, true); - if (!shorthand || !this._accept(4 /* CurlyClose */)) { - this._backTo(token); - return false; + return ret; + } + _replace(groups) { + let ret = ''; + for (const marker of this._children) { + if (marker instanceof FormatString) { + let value = groups[marker.index] || ''; + value = marker.resolve(value); + ret += value; } else { - parent.appendChild(new FormatString(Number(index), shorthand)); - return true; + ret += marker.toString(); } } - else if (this._accept(11 /* Plus */)) { - // ${1:+} - let ifValue = this._until(4 /* CurlyClose */); - if (ifValue) { - parent.appendChild(new FormatString(Number(index), undefined, ifValue, undefined)); - return true; - } + return ret; + } + toString() { + return ''; + } + toTextmateString() { + return `/${this.regexp.source}/${this.children.map(c => c.toTextmateString())}/${(this.regexp.ignoreCase ? 'i' : '') + (this.regexp.global ? 'g' : '')}`; + } + clone() { + let ret = new Transform(); + ret.regexp = new RegExp(this.regexp.source, '' + (this.regexp.ignoreCase ? 'i' : '') + (this.regexp.global ? 'g' : '')); + ret._children = this.children.map(child => child.clone()); + return ret; + } +} +exports.Transform = Transform; +class FormatString extends Marker { + constructor(index, shorthandName, ifValue, elseValue) { + super(); + this.index = index; + this.shorthandName = shorthandName; + this.ifValue = ifValue; + this.elseValue = elseValue; + } + resolve(value) { + if (this.shorthandName === 'upcase') { + return !value ? '' : value.toLocaleUpperCase(); } - else if (this._accept(12 /* Dash */)) { - // ${2:-} - let elseValue = this._until(4 /* CurlyClose */); - if (elseValue) { - parent.appendChild(new FormatString(Number(index), undefined, undefined, elseValue)); - return true; - } + else if (this.shorthandName === 'downcase') { + return !value ? '' : value.toLocaleLowerCase(); } - else if (this._accept(13 /* QuestionMark */)) { - // ${2:?:} - let ifValue = this._until(1 /* Colon */); - if (ifValue) { - let elseValue = this._until(4 /* CurlyClose */); - if (elseValue) { - parent.appendChild(new FormatString(Number(index), undefined, ifValue, elseValue)); - return true; - } - } + else if (this.shorthandName === 'capitalize') { + return !value ? '' : (value[0].toLocaleUpperCase() + value.substr(1)); + } + else if (this.shorthandName === 'pascalcase') { + return !value ? '' : this._toPascalCase(value); + } + else if (Boolean(value) && typeof this.ifValue === 'string') { + return this.ifValue; + } + else if (!Boolean(value) && typeof this.elseValue === 'string') { + return this.elseValue; } else { - // ${1:} - let elseValue = this._until(4 /* CurlyClose */); - if (elseValue) { - parent.appendChild(new FormatString(Number(index), undefined, undefined, elseValue)); - return true; - } + return value || ''; } - this._backTo(token); - return false; } - _parseAnything(marker) { - if (this._token.type !== 14 /* EOF */) { - let text = this._scanner.tokenText(this._token); - marker.appendChild(new Text(text)); - this._accept(undefined); - return true; + _toPascalCase(value) { + const match = value.match(/[a-z]+/gi); + if (!match) { + return value; } - return false; - } -} -exports.SnippetParser = SnippetParser; -//# sourceMappingURL=parser.js.map - -/***/ }), -/* 250 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const tslib_1 = __webpack_require__(3); -const vscode_languageserver_protocol_1 = __webpack_require__(150); -const completion_1 = tslib_1.__importDefault(__webpack_require__(251)); -const util_1 = __webpack_require__(177); -const position_1 = __webpack_require__(216); -const string_1 = __webpack_require__(213); -const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const snippet_1 = __webpack_require__(403); -const variableResolve_1 = __webpack_require__(404); -const logger = __webpack_require__(2)('snippets-session'); -class SnippetSession { - constructor(nvim, bufnr) { - this.nvim = nvim; - this.bufnr = bufnr; - this._isActive = false; - this._currId = 0; - // Get state of line where we inserted - this.version = 0; - this.preferComplete = false; - this._snippet = null; - this._onCancelEvent = new vscode_languageserver_protocol_1.Emitter(); - this.onCancel = this._onCancelEvent.event; - let config = workspace_1.default.getConfiguration('coc.preferences'); - let suggest = workspace_1.default.getConfiguration('suggest'); - this.preferComplete = config.get('preferCompleteThanJumpPlaceholder', suggest.get('preferCompleteThanJumpPlaceholder', false)); + return match.map(word => { + return word.charAt(0).toUpperCase() + + word.substr(1).toLowerCase(); + }) + .join(''); } - async start(snippetString, select = true, range) { - const { document, nvim } = this; - if (!document) - return false; - if (!range) { - let position = await workspace_1.default.getCursorPosition(); - range = vscode_languageserver_protocol_1.Range.create(position, position); - } - let position = range.start; - const formatOptions = await workspace_1.default.getFormatOptions(this.document.uri); - const currentLine = document.getline(position.line); - const currentIndent = currentLine.match(/^\s*/)[0]; - let inserted = normalizeSnippetString(snippetString, currentIndent, formatOptions); - const resolver = new variableResolve_1.SnippetVariableResolver(); - await resolver.init(document); - const snippet = new snippet_1.CocSnippet(inserted, position, resolver); - const edit = vscode_languageserver_protocol_1.TextEdit.replace(range, snippet.toString()); - if (snippetString.endsWith('\n') - && currentLine.slice(position.character).length) { - // make next line same indent - edit.newText = edit.newText + currentIndent; - inserted = inserted + currentIndent; + toTextmateString() { + let value = '${'; + value += this.index; + if (this.shorthandName) { + value += `:/${this.shorthandName}`; } - if (snippet.isPlainText) { - // insert as text - await document.applyEdits(nvim, [edit]); - let placeholder = snippet.finalPlaceholder; - await workspace_1.default.moveTo(placeholder.range.start); - return this._isActive; + else if (this.ifValue && this.elseValue) { + value += `:?${this.ifValue}:${this.elseValue}`; } - await document.patchChange(); - document.forceSync(); - this.version = document.version; - await document.applyEdits(nvim, [edit]); - if (this._isActive) { - // insert check - let placeholder = this.findPlaceholder(range); - // insert to placeholder - if (placeholder && !placeholder.isFinalTabstop) { - // don't repeat snippet insert - let index = this.snippet.insertSnippet(placeholder, inserted, range); - let p = this.snippet.getPlaceholder(index); - this._currId = p.id; - if (select) - await this.selectPlaceholder(p); - return true; - } + else if (this.ifValue) { + value += `:+${this.ifValue}`; } - // new snippet - this._snippet = snippet; - this._currId = snippet.firstPlaceholder.id; - if (select) - await this.selectPlaceholder(snippet.firstPlaceholder); - this.activate(); - return true; - } - activate() { - if (this._isActive) - return; - this._isActive = true; - this.nvim.call('coc#snippet#enable', [], true); - } - deactivate() { - if (this._isActive) { - this._isActive = false; - this._snippet = null; - this.nvim.call('coc#snippet#disable', [], true); - logger.debug("[SnippetManager::cancel]"); + else if (this.elseValue) { + value += `:-${this.elseValue}`; } - this._onCancelEvent.fire(void 0); - this._onCancelEvent.dispose(); - } - get isActive() { - return this._isActive; + value += '}'; + return value; } - async nextPlaceholder() { - await this.documentSynchronize(); - if (!this.isActive) - return; - let curr = this.placeholder; - let next = this.snippet.getNextPlaceholder(curr.index); - await this.selectPlaceholder(next); + clone() { + let ret = new FormatString(this.index, this.shorthandName, this.ifValue, this.elseValue); + return ret; } - async previousPlaceholder() { - await this.documentSynchronize(); - if (!this.isActive) - return; - let curr = this.placeholder; - let prev = this.snippet.getPrevPlaceholder(curr.index); - await this.selectPlaceholder(prev); +} +exports.FormatString = FormatString; +class Variable extends TransformableMarker { + constructor(name) { + super(); + this.name = name; } - async synchronizeUpdatedPlaceholders(change) { - if (!this.isActive || !this.document || this.document.version - this.version == 1) - return; - if (!('range' in change)) - return; - let edit = { range: change.range, newText: change.text }; - let { snippet } = this; - // change outside range - let adjusted = snippet.adjustTextEdit(edit); - if (adjusted) - return; - if (position_1.comparePosition(edit.range.start, snippet.range.end) > 0) { - if (!edit.newText) - return; - logger.info('Content change after snippet, cancelling snippet session'); - this.deactivate(); - return; - } - let placeholder = this.findPlaceholder(edit.range); - if (!placeholder) { - logger.info('Change outside placeholder, cancelling snippet session'); - this.deactivate(); - return; + resolve(resolver) { + let value = resolver.resolve(this); + if (value && value.indexOf('\n') !== -1) { + // get indent of previous Text child + let { children } = this.parent; + let idx = children.indexOf(this); + let previous = children[idx - 1]; + if (previous && previous instanceof Text) { + let ms = previous.value.match(/\n([ \t]*)$/); + if (ms) { + let lines = value.split('\n'); + let indents = lines.filter(s => s.length > 0).map(s => s.match(/^\s*/)[0]); + let minIndent = indents.length == 0 ? '' : + indents.reduce((p, c) => p.length < c.length ? p : c); + let newLines = lines.map((s, i) => { + return i == 0 || s.length == 0 || !s.startsWith(minIndent) ? s : + ms[1] + s.slice(minIndent.length); + }); + value = newLines.join('\n'); + } + } } - if (placeholder.isFinalTabstop) { - logger.info('Change final placeholder, cancelling snippet session'); - this.deactivate(); - return; + if (this.transform) { + value = this.transform.resolve(value || ''); } - this._currId = placeholder.id; - let { edits, delta } = snippet.updatePlaceholder(placeholder, edit); - if (!edits.length) - return; - this.version = this.document.version; - // let pos = await workspace.getCursorPosition() - await this.document.applyEdits(this.nvim, edits); - if (delta) { - await this.nvim.call('coc#util#move_cursor', delta); + if (value !== undefined) { + this._children = [new Text(value)]; + return true; } + return false; } - async selectCurrentPlaceholder(triggerAutocmd = true) { - let placeholder = this.snippet.getPlaceholderById(this._currId); - if (placeholder) - await this.selectPlaceholder(placeholder, triggerAutocmd); - } - async selectPlaceholder(placeholder, triggerAutocmd = true) { - let { nvim, document } = this; - if (!document || !placeholder) - return; - let { start, end } = placeholder.range; - const len = end.character - start.character; - const col = string_1.byteLength(document.getline(start.line).slice(0, start.character)) + 1; - this._currId = placeholder.id; - if (placeholder.choice) { - await nvim.call('coc#snippet#show_choices', [start.line + 1, col, len, placeholder.choice]); + toTextmateString() { + let transformString = ''; + if (this.transform) { + transformString = this.transform.toTextmateString(); + } + if (this.children.length === 0) { + return `\${${this.name}${transformString}}`; } else { - await this.select(placeholder.range, placeholder.value, triggerAutocmd); + return `\${${this.name}:${this.children.map(child => child.toTextmateString()).join('')}${transformString}}`; } } - async select(range, text, triggerAutocmd = true) { - let { document, nvim } = this; - let { start, end } = range; - let { textDocument } = document; - let len = textDocument.offsetAt(end) - textDocument.offsetAt(start); - let line = document.getline(start.line); - let col = line ? string_1.byteLength(line.slice(0, start.character)) : 0; - let endLine = document.getline(end.line); - let endCol = endLine ? string_1.byteLength(endLine.slice(0, end.character)) : 0; - nvim.setVar('coc_last_placeholder', { - current_text: text, - start: { line: start.line, col }, - end: { line: end.line, col: endCol } - }, true); - let [ve, selection, pumvisible, mode] = await nvim.eval('[&virtualedit, &selection, pumvisible(), mode()]'); - let move_cmd = ''; - if (pumvisible && this.preferComplete) { - let pre = completion_1.default.hasSelected() ? '' : '\\'; - await nvim.eval(`feedkeys("${pre}\\", 'in')`); - return; + clone() { + const ret = new Variable(this.name); + if (this.transform) { + ret.transform = this.transform.clone(); } - let resetVirtualEdit = false; - if (mode != 'n') - move_cmd += "\\"; - if (len == 0) { - if (col == 0 || (!mode.startsWith('i') && col < string_1.byteLength(line))) { - move_cmd += 'i'; + ret._children = this.children.map(child => child.clone()); + return ret; + } +} +exports.Variable = Variable; +function walk(marker, visitor) { + const stack = [...marker]; + while (stack.length > 0) { + const marker = stack.shift(); + const recurse = visitor(marker); + if (!recurse) { + break; + } + stack.unshift(...marker.children); + } +} +class TextmateSnippet extends Marker { + get placeholderInfo() { + if (!this._placeholders) { + // fill in placeholders + let all = []; + let last; + this.walk(candidate => { + if (candidate instanceof Placeholder) { + all.push(candidate); + last = !last || last.index < candidate.index ? candidate : last; + } + return true; + }); + this._placeholders = { all, last }; + } + return this._placeholders; + } + get placeholders() { + const { all } = this.placeholderInfo; + return all; + } + get maxIndexNumber() { + let { placeholders } = this; + return placeholders.reduce((curr, p) => { + return Math.max(curr, p.index); + }, 0); + } + get minIndexNumber() { + let { placeholders } = this; + let nums = placeholders.map(p => p.index); + nums.sort((a, b) => a - b); + if (nums.length > 1 && nums[0] == 0) + return nums[1]; + return nums[0] || 0; + } + insertSnippet(snippet, id, range) { + let placeholder = this.placeholders[id]; + if (!placeholder) + return; + let { index } = placeholder; + const document = vscode_languageserver_protocol_1.TextDocument.create('untitled:/1', 'snippet', 0, placeholder.toString()); + snippet = vscode_languageserver_protocol_1.TextDocument.applyEdits(document, [{ range, newText: snippet.replace(/\$0$/, '') }]); + let nested = new SnippetParser().parse(snippet, false); + let maxIndexAdded = nested.maxIndexNumber; + let totalAdd = maxIndexAdded + -1; + for (let p of nested.placeholders) { + if (p.isFinalTabstop) { + p.index = maxIndexAdded + index + 1; } else { - move_cmd += 'a'; + p.index = p.index + index; } } - else { - move_cmd += 'v'; - endCol = await this.getVirtualCol(end.line + 1, endCol); - if (selection == 'inclusive') { - if (end.character == 0) { - move_cmd += `${end.line}G`; + this.walk(m => { + if (m instanceof Placeholder && m.index > index) { + m.index = m.index + totalAdd + 1; + } + return true; + }); + this.replace(placeholder, nested.children); + return index + 1; + } + updatePlaceholder(id, val) { + const placeholder = this.placeholders[id]; + for (let p of this.placeholders) { + if (p.index == placeholder.index) { + let child = p.children[0]; + let newText = p.transform ? p.transform.resolve(val) : val; + if (child) { + p.setOnlyChild(new Text(newText)); } else { - move_cmd += `${end.line + 1}G${endCol}|`; + p.appendChild(new Text(newText)); } } - else if (selection == 'old') { - move_cmd += `${end.line + 1}G${endCol}|`; - } - else { - move_cmd += `${end.line + 1}G${endCol + 1}|`; - } - col = await this.getVirtualCol(start.line + 1, col); - move_cmd += `o${start.line + 1}G${col + 1}|o\\`; - } - nvim.pauseNotification(); - if (ve != 'onemore') { - resetVirtualEdit = true; - nvim.setOption('virtualedit', 'onemore', true); } - nvim.command(`noa call cursor(${start.line + 1},${col + (move_cmd == 'a' ? 0 : 1)})`, true); - nvim.call('eval', [`feedkeys("${move_cmd}", 'in')`], true); - if (resetVirtualEdit) - nvim.setOption('virtualedit', ve, true); - if (workspace_1.default.env.isVim) - nvim.command('redraw', true); - await nvim.resumeNotification(); - if (triggerAutocmd) - nvim.command('silent doautocmd User CocJumpPlaceholder', true); - } - async getVirtualCol(line, col) { - let { nvim } = this; - return await nvim.eval(`virtcol([${line}, ${col}])`); + this._placeholders = undefined; } - async documentSynchronize() { - if (!this.isActive) - return; - await this.document.patchChange(); - this.document.forceSync(); - await util_1.wait(50); + /** + * newText after update with value + */ + getPlaceholderText(id, value) { + const placeholder = this.placeholders[id]; + if (!placeholder) + return value; + return placeholder.transform ? placeholder.transform.resolve(value) : value; } - async checkPosition() { - if (!this.isActive) - return; - let position = await workspace_1.default.getCursorPosition(); - if (this.snippet && position_1.positionInRange(position, this.snippet.range) != 0) { - logger.info('Cursor insert out of range, cancelling snippet session'); - this.deactivate(); + offset(marker) { + let pos = 0; + let found = false; + this.walk(candidate => { + if (candidate === marker) { + found = true; + return false; + } + pos += candidate.len(); + return true; + }); + if (!found) { + return -1; } + return pos; } - findPlaceholder(range) { - if (!this.snippet) - return null; - let { placeholder } = this; - if (position_1.rangeInRange(range, placeholder.range)) - return placeholder; - return this.snippet.getPlaceholderByRange(range) || null; - } - get placeholder() { - if (!this.snippet) - return; - return this.snippet.getPlaceholderById(this._currId); - } - get snippet() { - return this._snippet; - } - get document() { - return workspace_1.default.getDocument(this.bufnr); + fullLen(marker) { + let ret = 0; + walk([marker], marker => { + ret += marker.len(); + return true; + }); + return ret; } -} -exports.SnippetSession = SnippetSession; -function normalizeSnippetString(snippet, indent, opts) { - let lines = snippet.split(/\r?\n/); - let ind = opts.insertSpaces ? ' '.repeat(opts.tabSize) : '\t'; - let tabSize = opts.tabSize || 2; - lines = lines.map((line, idx) => { - let space = line.match(/^\s*/)[0]; - let pre = space; - let isTab = space.startsWith('\t'); - if (isTab && opts.insertSpaces) { - pre = ind.repeat(space.length); - } - else if (!isTab && !opts.insertSpaces) { - pre = ind.repeat(space.length / tabSize); + enclosingPlaceholders(placeholder) { + let ret = []; + let { parent } = placeholder; + while (parent) { + if (parent instanceof Placeholder) { + ret.push(parent); + } + parent = parent.parent; } - return (idx == 0 || line.length == 0 ? '' : indent) + pre + line.slice(space.length); - }); - return lines.join('\n'); -} -exports.normalizeSnippetString = normalizeSnippetString; -//# sourceMappingURL=session.js.map - -/***/ }), -/* 251 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const tslib_1 = __webpack_require__(3); -const debounce_1 = tslib_1.__importDefault(__webpack_require__(179)); -const vscode_languageserver_protocol_1 = __webpack_require__(150); -const events_1 = tslib_1.__importDefault(__webpack_require__(149)); -const sources_1 = tslib_1.__importDefault(__webpack_require__(252)); -const util_1 = __webpack_require__(177); -const string_1 = __webpack_require__(213); -const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const complete_1 = tslib_1.__importDefault(__webpack_require__(400)); -const floating_1 = tslib_1.__importDefault(__webpack_require__(402)); -const logger = __webpack_require__(2)('completion'); -const completeItemKeys = ['abbr', 'menu', 'info', 'kind', 'icase', 'dup', 'empty', 'user_data']; -class Completion { - constructor() { - // current input string - this.activated = false; - this.disposables = []; - this.complete = null; - this.recentScores = {}; - this.changedTick = 0; - this.insertCharTs = 0; - this.insertLeaveTs = 0; - // only used when no pum change event - this.isResolving = false; + return ret; } - init() { - this.config = this.getCompleteConfig(); - this.floating = new floating_1.default(); - events_1.default.on('InsertCharPre', this.onInsertCharPre, this, this.disposables); - events_1.default.on('InsertLeave', this.onInsertLeave, this, this.disposables); - events_1.default.on('InsertEnter', this.onInsertEnter, this, this.disposables); - events_1.default.on('TextChangedP', this.onTextChangedP, this, this.disposables); - events_1.default.on('TextChangedI', this.onTextChangedI, this, this.disposables); - events_1.default.on('CompleteDone', this.onCompleteDone, this, this.disposables); - events_1.default.on('MenuPopupChanged', this.onPumChange, this, this.disposables); - events_1.default.on('CursorMovedI', debounce_1.default(async (bufnr, cursor) => { - // try trigger completion - let doc = workspace_1.default.getDocument(bufnr); - if (this.isActivated || !doc || cursor[1] == 1 || !this.latestInsertChar) - return; - let line = doc.getline(cursor[0] - 1); - if (!line) - return; - let pre = string_1.byteSlice(line, 0, cursor[1] - 1); - if (sources_1.default.shouldTrigger(pre, doc.filetype)) { - await this.triggerCompletion(doc, pre, false); - } - }, 50)); - workspace_1.default.onDidChangeConfiguration(e => { - if (e.affectsConfiguration('suggest')) { - Object.assign(this.config, this.getCompleteConfig()); + resolveVariables(resolver) { + this.walk(candidate => { + if (candidate instanceof Variable) { + if (candidate.resolve(resolver)) { + this._placeholders = undefined; + } } - }, null, this.disposables); + return true; + }); + return this; } - get nvim() { - return workspace_1.default.nvim; + appendChild(child) { + this._placeholders = undefined; + return super.appendChild(child); } - get option() { - if (!this.complete) - return null; - return this.complete.option; + replace(child, others) { + this._placeholders = undefined; + return super.replace(child, others); } - addRecent(word, bufnr) { - if (!word) - return; - this.recentScores[`${bufnr}|${word}`] = Date.now(); + toTextmateString() { + return this.children.reduce((prev, cur) => prev + cur.toTextmateString(), ''); } - async getPreviousContent(document) { - let [, lnum, col] = await this.nvim.call('getcurpos'); - if (this.option && lnum != this.option.linenr) - return null; - let line = document.getline(lnum - 1); - return col == 1 ? '' : string_1.byteSlice(line, 0, col - 1); + clone() { + let ret = new TextmateSnippet(); + this._children = this.children.map(child => child.clone()); + return ret; } - getResumeInput(pre) { - let { option, activated } = this; - if (!activated) - return null; - if (!pre) - return ''; - let input = string_1.byteSlice(pre, option.col); - if (option.blacklist && option.blacklist.indexOf(input) !== -1) - return null; - return input; + walk(visitor) { + walk(this.children, visitor); } - get bufnr() { - let { option } = this; - return option ? option.bufnr : null; +} +exports.TextmateSnippet = TextmateSnippet; +class SnippetParser { + constructor() { + this._scanner = new Scanner(); } - get isActivated() { - return this.activated; + static escape(value) { + return value.replace(/\$|}|\\/g, '\\$&'); } - getCompleteConfig() { - let config = workspace_1.default.getConfiguration('coc.preferences'); - let suggest = workspace_1.default.getConfiguration('suggest'); - function getConfig(key, defaultValue) { - return config.get(key, suggest.get(key, defaultValue)); + text(value) { + return this.parse(value).toString(); + } + parse(value, insertFinalTabstop) { + this._scanner.text(value); + this._token = this._scanner.next(); + const snippet = new TextmateSnippet(); + while (this._parse(snippet)) { + // nothing } - let keepCompleteopt = getConfig('keepCompleteopt', false); - let autoTrigger = getConfig('autoTrigger', 'always'); - if (keepCompleteopt) { - let { completeOpt } = workspace_1.default; - if (!completeOpt.includes('noinsert') && !completeOpt.includes('noselect')) { - autoTrigger = 'none'; + // fill in values for placeholders. the first placeholder of an index + // that has a value defines the value for all placeholders with that index + const placeholderDefaultValues = new Map(); + const incompletePlaceholders = []; + snippet.walk(marker => { + if (marker instanceof Placeholder) { + if (marker.isFinalTabstop) { + placeholderDefaultValues.set(0, undefined); + } + else if (!placeholderDefaultValues.has(marker.index) && marker.children.length > 0) { + placeholderDefaultValues.set(marker.index, marker.children); + } + else { + incompletePlaceholders.push(marker); + } + } + return true; + }); + for (const placeholder of incompletePlaceholders) { + if (placeholderDefaultValues.has(placeholder.index)) { + const clone = new Placeholder(placeholder.index); + clone.transform = placeholder.transform; + for (const child of placeholderDefaultValues.get(placeholder.index)) { + let marker = child.clone(); + if (clone.transform) { + if (marker instanceof Text) { + marker = new Text(clone.transform.resolve(marker.value)); + } + else { + for (let child of marker.children) { + if (child instanceof Text) { + marker.replace(child, [new Text(clone.transform.resolve(child.value))]); + break; + } + } + } + } + clone.appendChild(marker); + } + snippet.replace(placeholder, [clone]); } } - let acceptSuggestionOnCommitCharacter = workspace_1.default.env.pumevent && getConfig('acceptSuggestionOnCommitCharacter', false); - return { - autoTrigger, - keepCompleteopt, - defaultSortMethod: getConfig('defaultSortMethod', 'length'), - removeDuplicateItems: getConfig('removeDuplicateItems', false), - disableMenuShortcut: getConfig('disableMenuShortcut', false), - acceptSuggestionOnCommitCharacter, - disableKind: getConfig('disableKind', false), - disableMenu: getConfig('disableMenu', false), - previewIsKeyword: getConfig('previewIsKeyword', '@,48-57,_192-255'), - enablePreview: getConfig('enablePreview', false), - enablePreselect: getConfig('enablePreselect', false), - maxPreviewWidth: getConfig('maxPreviewWidth', 50), - labelMaxLength: getConfig('labelMaxLength', 100), - triggerAfterInsertEnter: getConfig('triggerAfterInsertEnter', false), - noselect: getConfig('noselect', true), - numberSelect: getConfig('numberSelect', false), - maxItemCount: getConfig('maxCompleteItemCount', 50), - timeout: getConfig('timeout', 500), - minTriggerInputLength: getConfig('minTriggerInputLength', 1), - snippetIndicator: getConfig('snippetIndicator', '~'), - fixInsertedWord: getConfig('fixInsertedWord', true), - localityBonus: getConfig('localityBonus', true), - highPrioritySourceLimit: getConfig('highPrioritySourceLimit', null), - lowPrioritySourceLimit: getConfig('lowPrioritySourceLimit', null), - asciiCharactersOnly: getConfig('asciiCharactersOnly', false) - }; - } - async startCompletion(option) { - workspace_1.default.bufnr = option.bufnr; - let document = workspace_1.default.getDocument(option.bufnr); - if (!document) - return; - // use fixed filetype - option.filetype = document.filetype; - this.document = document; - try { - await this._doComplete(option); - } - catch (e) { - this.stop(); - workspace_1.default.showMessage(`Error happens on complete: ${e.message}`, 'error'); - logger.error(e.stack); + if (!placeholderDefaultValues.has(0) && insertFinalTabstop) { + // the snippet uses placeholders but has no + // final tabstop defined -> insert at the end + snippet.appendChild(new Placeholder(0)); } + return snippet; } - async resumeCompletion(pre, search, force = false) { - let { document, complete, activated } = this; - if (!activated || !complete.results) - return; - if (search == this.input && !force) - return; - let last = search == null ? '' : search.slice(-1); - if (last.length == 0 || - /\s/.test(last) || - sources_1.default.shouldTrigger(pre, document.filetype) || - search.length < complete.input.length) { - this.stop(); - return; - } - this.input = search; - let items; - if (complete.isIncomplete && document.chars.isKeywordChar(last)) { - await document.patchChange(); - document.forceSync(); - await util_1.wait(30); - items = await complete.completeInComplete(search); - // check search change - let content = await this.getPreviousContent(document); - let curr = this.getResumeInput(content); - if (curr != search) - return; + _accept(type, value) { + if (type === undefined || this._token.type === type) { + let ret = !value ? true : this._scanner.tokenText(this._token); + this._token = this._scanner.next(); + return ret; } - else { - items = complete.filterResults(search); + return false; + } + _backTo(token) { + this._scanner.pos = token.pos + token.len; + this._token = token; + return false; + } + _until(type) { + if (this._token.type === 14 /* EOF */) { + return false; } - if (!this.isActivated) - return; - if (!complete.isCompleting && (!items || items.length === 0)) { - this.stop(); - return; + let start = this._token; + while (this._token.type !== type) { + this._token = this._scanner.next(); + if (this._token.type === 14 /* EOF */) { + return false; + } } - await this.showCompletion(this.option.col, items); + let value = this._scanner.value.substring(start.pos, this._token.pos); + this._token = this._scanner.next(); + return value; } - hasSelected() { - if (workspace_1.default.env.pumevent) - return this.currItem != null; - if (this.config.noselect === false) - return true; - return this.isResolving; + _parse(marker) { + return this._parseEscaped(marker) + || this._parseTabstopOrVariableName(marker) + || this._parseComplexPlaceholder(marker) + || this._parseComplexVariable(marker) + || this._parseAnything(marker); } - async showCompletion(col, items) { - let { nvim, document, option } = this; - let { numberSelect, disableKind, labelMaxLength, disableMenuShortcut, disableMenu } = this.config; - let preselect = this.config.enablePreselect ? items.findIndex(o => o.preselect == true) : -1; - if (numberSelect && option.input.length && !/^\d/.test(option.input)) { - items = items.map((item, i) => { - let idx = i + 1; - if (i < 9) { - return Object.assign({}, item, { - abbr: item.abbr ? `${idx} ${item.abbr}` : `${idx} ${item.word}` - }); + // \$, \\, \} -> just text + _parseEscaped(marker) { + let value; + if (value = this._accept(5 /* Backslash */, true)) { // tslint:disable-line + // saw a backslash, append escaped token or that backslash + value = this._accept(0 /* Dollar */, true) + || this._accept(4 /* CurlyClose */, true) + || this._accept(5 /* Backslash */, true) + || value; + marker.appendChild(new Text(value)); + return true; + } + return false; + } + // $foo -> variable, $1 -> tabstop + _parseTabstopOrVariableName(parent) { + let value; + const token = this._token; + const match = this._accept(0 /* Dollar */) + && (value = this._accept(9 /* VariableName */, true) || this._accept(8 /* Int */, true)); + if (!match) { + return this._backTo(token); + } + parent.appendChild(/^\d+$/.test(value) + ? new Placeholder(Number(value)) + : new Variable(value)); + return true; + } + // ${1:}, ${1} -> placeholder + _parseComplexPlaceholder(parent) { + let index; + const token = this._token; + const match = this._accept(0 /* Dollar */) + && this._accept(3 /* CurlyOpen */) + && (index = this._accept(8 /* Int */, true)); + if (!match) { + return this._backTo(token); + } + const placeholder = new Placeholder(Number(index)); + if (this._accept(1 /* Colon */)) { + // ${1:} + while (true) { + // ...} -> done + if (this._accept(4 /* CurlyClose */)) { + parent.appendChild(placeholder); + return true; } - return item; - }); - nvim.call('coc#_map', [], true); + if (this._parse(placeholder)) { + continue; + } + // fallback + parent.appendChild(new Text('${' + index + ':')); + placeholder.children.forEach(parent.appendChild, parent); + return true; + } } - this.changedTick = document.changedtick; - let validKeys = completeItemKeys.slice(); - if (disableKind) - validKeys = validKeys.filter(s => s != 'kind'); - if (disableMenu) - validKeys = validKeys.filter(s => s != 'menu'); - let vimItems = items.map(item => { - let obj = { word: item.word, equal: 1 }; - for (let key of validKeys) { - if (item.hasOwnProperty(key)) { - if (disableMenuShortcut && key == 'menu') { - obj[key] = item[key].replace(/\[\w+\]$/, ''); - } - else if (key == 'abbr' && item[key].length > labelMaxLength) { - obj[key] = item[key].slice(0, labelMaxLength); + else if (placeholder.index > 0 && this._accept(7 /* Pipe */)) { + // ${1|one,two,three|} + const choice = new Choice(); + while (true) { + if (this._parseChoiceElement(choice)) { + if (this._accept(2 /* Comma */)) { + // opt, -> more + continue; } - else { - obj[key] = item[key]; + if (this._accept(7 /* Pipe */)) { + placeholder.appendChild(choice); + if (this._accept(4 /* CurlyClose */)) { + // ..|} -> done + parent.appendChild(placeholder); + return true; + } } } + this._backTo(token); + return false; } - return obj; - }); - nvim.call('coc#_do_complete', [col, vimItems, preselect], true); - } - async _doComplete(option) { - let { source } = option; - let { nvim, config, document } = this; - // current input - this.input = option.input; - let arr = []; - if (source == null) { - arr = sources_1.default.getCompleteSources(option); - } - else { - let s = sources_1.default.getSource(source); - if (s) - arr.push(s); - } - if (!arr.length) - return; - let complete = new complete_1.default(option, document, this.recentScores, config, arr, nvim); - this.start(complete); - let items = await this.complete.doComplete(); - if (complete.isCanceled) - return; - if (items.length == 0 && !complete.isCompleting) { - this.stop(); - return; } - complete.onDidComplete(async () => { - let content = await this.getPreviousContent(document); - let search = this.getResumeInput(content); - if (complete.isCanceled) - return; - let hasSelected = this.hasSelected(); - if (hasSelected && this.completeOpt.indexOf('noselect') !== -1) - return; - if (search == this.option.input) { - let items = complete.filterResults(search, Math.floor(Date.now() / 1000)); - await this.showCompletion(option.col, items); - return; - } - await this.resumeCompletion(content, search, true); - }); - if (items.length) { - let content = await this.getPreviousContent(document); - let search = this.getResumeInput(content); - if (complete.isCanceled) - return; - if (search == this.option.input) { - await this.showCompletion(option.col, items); - return; + else if (this._accept(6 /* Forwardslash */)) { + // ${1///} + if (this._parseTransform(placeholder)) { + parent.appendChild(placeholder); + return true; } - await this.resumeCompletion(content, search, true); + this._backTo(token); + return false; } - } - async onTextChangedP() { - let { option, document } = this; - if (!option) - return; - await document.patchChange(); - let hasInsert = this.latestInsert != null; - this.lastInsert = null; - // avoid trigger filter on pumvisible - if (document.changedtick == this.changedTick) - return; - let line = document.getline(option.linenr - 1); - let curr = line.match(/^\s*/)[0]; - let ind = option.line.match(/^\s*/)[0]; - // indent change - if (ind.length != curr.length) { - this.stop(); - return; + else if (this._accept(4 /* CurlyClose */)) { + // ${1} + parent.appendChild(placeholder); + return true; } - if (!hasInsert) { - // this could be wrong, but can't avoid. - this.isResolving = true; - return; + else { + // ${1 <- missing curly or colon + return this._backTo(token); } - let pre = await this.getPreviousContent(document); - if (!pre) - return; - let search = this.getResumeInput(pre); - if (sources_1.default.shouldTrigger(pre, document.filetype)) { - await this.triggerCompletion(document, pre, false); + } + _parseChoiceElement(parent) { + const token = this._token; + const values = []; + while (true) { + if (this._token.type === 2 /* Comma */ || this._token.type === 7 /* Pipe */) { + break; + } + let value; + if (value = this._accept(5 /* Backslash */, true)) { // tslint:disable-line + // \, \|, or \\ + value = this._accept(2 /* Comma */, true) + || this._accept(7 /* Pipe */, true) + || this._accept(5 /* Backslash */, true) + || value; + } + else { + value = this._accept(undefined, true); + } + if (!value) { + // EOF + this._backTo(token); + return false; + } + values.push(value); } - else { - await this.resumeCompletion(pre, search); + if (values.length === 0) { + this._backTo(token); + return false; } + parent.appendChild(new Text(values.join(''))); + return true; } - async onTextChangedI(bufnr) { - let { nvim, latestInsertChar } = this; - this.lastInsert = null; - let document = workspace_1.default.getDocument(workspace_1.default.bufnr); - if (!document) - return; - await document.patchChange(); - if (!this.isActivated) { - if (!latestInsertChar) - return; - let pre = await this.getPreviousContent(document); - await this.triggerCompletion(document, pre); - return; + // ${foo:}, ${foo} -> variable + _parseComplexVariable(parent) { + let name; + const token = this._token; + const match = this._accept(0 /* Dollar */) + && this._accept(3 /* CurlyOpen */) + && (name = this._accept(9 /* VariableName */, true)); + if (!match) { + return this._backTo(token); } - if (bufnr !== this.bufnr) - return; - // check commit character - if (this.config.acceptSuggestionOnCommitCharacter - && this.currItem - && latestInsertChar - && !this.document.isWord(latestInsertChar)) { - let resolvedItem = this.getCompleteItem(this.currItem); - if (sources_1.default.shouldCommit(resolvedItem, latestInsertChar)) { - let { linenr, col, line, colnr } = this.option; - this.stop(); - let { word } = resolvedItem; - let newLine = `${line.slice(0, col)}${word}${latestInsertChar}${line.slice(colnr - 1)}`; - await nvim.call('coc#util#setline', [linenr, newLine]); - let curcol = col + word.length + 2; - await nvim.call('cursor', [linenr, curcol]); - return; + const variable = new Variable(name); + if (this._accept(1 /* Colon */)) { + // ${foo:} + while (true) { + // ...} -> done + if (this._accept(4 /* CurlyClose */)) { + parent.appendChild(variable); + return true; + } + if (this._parse(variable)) { + continue; + } + // fallback + parent.appendChild(new Text('${' + name + ':')); + variable.children.forEach(parent.appendChild, parent); + return true; } } - let content = await this.getPreviousContent(document); - if (content == null) { - // cursor line changed - this.stop(); - return; + else if (this._accept(6 /* Forwardslash */)) { + // ${foo///} + if (this._parseTransform(variable)) { + parent.appendChild(variable); + return true; + } + this._backTo(token); + return false; } - // check trigger character - if (sources_1.default.shouldTrigger(content, document.filetype)) { - await this.triggerCompletion(document, content, false); - return; + else if (this._accept(4 /* CurlyClose */)) { + // ${foo} + parent.appendChild(variable); + return true; } - if (!this.isActivated || this.complete.isEmpty) - return; - let search = content.slice(string_1.characterIndex(content, this.option.col)); - return await this.resumeCompletion(content, search); - } - async triggerCompletion(document, pre, checkTrigger = true) { - // check trigger - if (checkTrigger) { - let shouldTrigger = await this.shouldTrigger(document, pre); - if (!shouldTrigger) - return; + else { + // ${foo <- missing curly or colon + return this._backTo(token); } - let option = await this.nvim.call('coc#util#get_complete_option'); - if (!option) - return; - this.fixCompleteOption(option); - option.triggerCharacter = pre.slice(-1); - logger.debug('trigger completion with', option); - await this.startCompletion(option); } - fixCompleteOption(opt) { - if (workspace_1.default.isVim) { - for (let key of ['word', 'input', 'line', 'filetype']) { - if (opt[key] == null) { - opt[key] = ''; + _parseTransform(parent) { + // ...//} + let transform = new Transform(); + let regexValue = ''; + let regexOptions = ''; + // (1) /regex + while (true) { + if (this._accept(6 /* Forwardslash */)) { + break; + } + let escaped; + if (escaped = this._accept(5 /* Backslash */, true)) { // tslint:disable-line + escaped = this._accept(6 /* Forwardslash */, true) || escaped; + regexValue += escaped; + continue; + } + if (this._token.type !== 14 /* EOF */) { + regexValue += this._accept(undefined, true); + continue; + } + return false; + } + // (2) /format + while (true) { + if (this._accept(6 /* Forwardslash */)) { + break; + } + let escaped; + if (escaped = this._accept(5 /* Backslash */, true)) { // tslint:disable-line + escaped = this._accept(6 /* Forwardslash */, true) || escaped; + transform.appendChild(new Text(escaped)); + continue; + } + if (this._parseFormatString(transform) || this._parseAnything(transform)) { + let text = transform.children[0]; + if (text && text.value && text.value.indexOf('\\n') !== -1) { + text.value = text.value.replace(/\\n/g, '\n'); } + continue; } + return false; + } + // (3) /option + while (true) { + if (this._accept(4 /* CurlyClose */)) { + break; + } + if (this._token.type !== 14 /* EOF */) { + regexOptions += this._accept(undefined, true); + continue; + } + return false; } - } - async onCompleteDone(item) { - let { document } = this; - if (!this.isActivated || !document || !item.hasOwnProperty('word')) - return; - let visible = await this.nvim.call('pumvisible'); - if (visible) - return; - let opt = Object.assign({}, this.option); - let resolvedItem = this.getCompleteItem(item); - this.stop(); - if (!resolvedItem) - return; - let timestamp = this.insertCharTs; - let insertLeaveTs = this.insertLeaveTs; try { - await sources_1.default.doCompleteResolve(resolvedItem, (new vscode_languageserver_protocol_1.CancellationTokenSource()).token); - this.addRecent(resolvedItem.word, document.bufnr); - await util_1.wait(50); - if (this.insertCharTs != timestamp - || this.insertLeaveTs != insertLeaveTs) - return; - await document.patchChange(); - let content = await this.getPreviousContent(document); - if (!content.endsWith(resolvedItem.word)) - return; - await sources_1.default.doCompleteDone(resolvedItem, opt); - document.forceSync(); + transform.regexp = new RegExp(regexValue, regexOptions); } catch (e) { - // tslint:disable-next-line:no-console - console.error(e.stack); - logger.error(`error on complete done`, e.stack); + // invalid regexp + return false; } + parent.transform = transform; + return true; } - async onInsertLeave(bufnr) { - this.insertLeaveTs = Date.now(); - if (this.isActivated) { - let doc = workspace_1.default.getDocument(bufnr); - if (doc) - doc.forceSync(); - this.stop(); + _parseFormatString(parent) { + const token = this._token; + if (!this._accept(0 /* Dollar */)) { + return false; } - } - async onInsertEnter(bufnr) { - if (!this.config.triggerAfterInsertEnter) - return; - let document = workspace_1.default.getDocument(bufnr); - if (!document) - return; - await document.patchChange(); - if (!document) - return; - let cursor = await this.nvim.call('coc#util#cursor'); - let line = document.getline(cursor[0]); - let pre = string_1.byteSlice(line, 0, cursor[1]); - if (!pre) - return; - await this.triggerCompletion(document, pre, false); - } - async onInsertCharPre(character) { - this.lastInsert = { - character, - timestamp: Date.now(), - }; - this.insertCharTs = this.lastInsert.timestamp; - } - get latestInsert() { - let { lastInsert } = this; - if (!lastInsert || Date.now() - lastInsert.timestamp > 500) { - return null; + let complex = false; + if (this._accept(3 /* CurlyOpen */)) { + complex = true; } - return lastInsert; - } - get latestInsertChar() { - let { latestInsert } = this; - if (!latestInsert) - return ''; - return latestInsert.character; - } - async shouldTrigger(document, pre) { - if (pre.length == 0 || /\s/.test(pre[pre.length - 1])) - return false; - let autoTrigger = this.config.autoTrigger; - if (autoTrigger == 'none') + let index = this._accept(8 /* Int */, true); + if (!index) { + this._backTo(token); return false; - if (sources_1.default.shouldTrigger(pre, document.filetype)) + } + else if (!complex) { + // $1 + parent.appendChild(new FormatString(Number(index))); return true; - if (autoTrigger !== 'always') + } + else if (this._accept(4 /* CurlyClose */)) { + // ${1} + parent.appendChild(new FormatString(Number(index))); + return true; + } + else if (!this._accept(1 /* Colon */)) { + this._backTo(token); return false; - let last = pre.slice(-1); - if (last && (document.isWord(pre.slice(-1)) || last.codePointAt(0) > 255)) { - let minLength = this.config.minTriggerInputLength; - if (minLength == 1) + } + if (this._accept(6 /* Forwardslash */)) { + // ${1:/upcase} + let shorthand = this._accept(9 /* VariableName */, true); + if (!shorthand || !this._accept(4 /* CurlyClose */)) { + this._backTo(token); + return false; + } + else { + parent.appendChild(new FormatString(Number(index), shorthand)); return true; - let input = this.getInput(document, pre); - return input.length >= minLength; + } } - return false; - } - async onPumChange(ev) { - if (!this.activated) - return; - if (this.document && this.document.uri.endsWith('%5BCommand%20Line%5D')) - return; - this.cancel(); - let { completed_item, col, row, height, width, scrollbar } = ev; - let bounding = { col, row, height, width, scrollbar }; - this.currItem = completed_item.hasOwnProperty('word') ? completed_item : null; - // it's pum change by vim, ignore it - if (this.lastInsert) - return; - let resolvedItem = this.getCompleteItem(completed_item); - if (!resolvedItem) { - this.floating.close(); - return; + else if (this._accept(11 /* Plus */)) { + // ${1:+} + let ifValue = this._until(4 /* CurlyClose */); + if (ifValue) { + parent.appendChild(new FormatString(Number(index), undefined, ifValue, undefined)); + return true; + } } - let source = this.resolveTokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource(); - let { token } = source; - await sources_1.default.doCompleteResolve(resolvedItem, token); - if (token.isCancellationRequested) - return; - let docs = resolvedItem.documentation; - if (!docs && resolvedItem.info) { - let { info } = resolvedItem; - let isText = /^[\w-\s.,\t]+$/.test(info); - docs = [{ filetype: isText ? 'txt' : this.document.filetype, content: info }]; + else if (this._accept(12 /* Dash */)) { + // ${2:-} + let elseValue = this._until(4 /* CurlyClose */); + if (elseValue) { + parent.appendChild(new FormatString(Number(index), undefined, undefined, elseValue)); + return true; + } } - if (!docs || docs.length == 0) { - this.floating.close(); + else if (this._accept(13 /* QuestionMark */)) { + // ${2:?:} + let ifValue = this._until(1 /* Colon */); + if (ifValue) { + let elseValue = this._until(4 /* CurlyClose */); + if (elseValue) { + parent.appendChild(new FormatString(Number(index), undefined, ifValue, elseValue)); + return true; + } + } } else { - if (token.isCancellationRequested) - return; - await this.floating.show(docs, bounding, token); + // ${1:} + let elseValue = this._until(4 /* CurlyClose */); + if (elseValue) { + parent.appendChild(new FormatString(Number(index), undefined, undefined, elseValue)); + return true; + } } - this.resolveTokenSource = null; + this._backTo(token); + return false; } - start(complete) { - let { activated } = this; - this.activated = true; - this.isResolving = false; - if (activated) { - this.complete.dispose(); + _parseAnything(marker) { + if (this._token.type !== 14 /* EOF */) { + let text = this._scanner.tokenText(this._token); + marker.appendChild(new Text(text)); + this._accept(undefined); + return true; } - this.complete = complete; - if (!this.config.keepCompleteopt) { - this.nvim.command(`noa set completeopt=${this.completeOpt}`, true); + return false; + } +} +exports.SnippetParser = SnippetParser; +//# sourceMappingURL=parser.js.map + +/***/ }), +/* 252 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const tslib_1 = __webpack_require__(3); +const vscode_languageserver_protocol_1 = __webpack_require__(150); +const completion_1 = tslib_1.__importDefault(__webpack_require__(253)); +const util_1 = __webpack_require__(177); +const position_1 = __webpack_require__(216); +const string_1 = __webpack_require__(213); +const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); +const snippet_1 = __webpack_require__(399); +const variableResolve_1 = __webpack_require__(400); +const logger = __webpack_require__(2)('snippets-session'); +class SnippetSession { + constructor(nvim, bufnr) { + this.nvim = nvim; + this.bufnr = bufnr; + this._isActive = false; + this._currId = 0; + // Get state of line where we inserted + this.version = 0; + this.preferComplete = false; + this._snippet = null; + this._onCancelEvent = new vscode_languageserver_protocol_1.Emitter(); + this.onCancel = this._onCancelEvent.event; + let config = workspace_1.default.getConfiguration('coc.preferences'); + let suggest = workspace_1.default.getConfiguration('suggest'); + this.preferComplete = config.get('preferCompleteThanJumpPlaceholder', suggest.get('preferCompleteThanJumpPlaceholder', false)); + } + async start(snippetString, select = true, range) { + const { document, nvim } = this; + if (!document) + return false; + if (!range) { + let position = await workspace_1.default.getCursorPosition(); + range = vscode_languageserver_protocol_1.Range.create(position, position); } - this.document.forceSync(true); - this.document.paused = true; + let position = range.start; + const formatOptions = await workspace_1.default.getFormatOptions(this.document.uri); + const currentLine = document.getline(position.line); + const currentIndent = currentLine.match(/^\s*/)[0]; + let inserted = normalizeSnippetString(snippetString, currentIndent, formatOptions); + const resolver = new variableResolve_1.SnippetVariableResolver(); + await resolver.init(document); + const snippet = new snippet_1.CocSnippet(inserted, position, resolver); + const edit = vscode_languageserver_protocol_1.TextEdit.replace(range, snippet.toString()); + if (snippetString.endsWith('\n') + && currentLine.slice(position.character).length) { + // make next line same indent + edit.newText = edit.newText + currentIndent; + inserted = inserted + currentIndent; + } + if (snippet.isPlainText) { + // insert as text + await document.applyEdits(nvim, [edit]); + let placeholder = snippet.finalPlaceholder; + await workspace_1.default.moveTo(placeholder.range.start); + return this._isActive; + } + await document.patchChange(); + document.forceSync(); + this.version = document.version; + await document.applyEdits(nvim, [edit]); + if (this._isActive) { + // insert check + let placeholder = this.findPlaceholder(range); + // insert to placeholder + if (placeholder && !placeholder.isFinalTabstop) { + // don't repeat snippet insert + let index = this.snippet.insertSnippet(placeholder, inserted, range); + let p = this.snippet.getPlaceholder(index); + this._currId = p.id; + if (select) + await this.selectPlaceholder(p); + return true; + } + } + // new snippet + this._snippet = snippet; + this._currId = snippet.firstPlaceholder.id; + if (select) + await this.selectPlaceholder(snippet.firstPlaceholder); + this.activate(); + return true; } - cancel() { - if (this.resolveTokenSource) { - this.resolveTokenSource.cancel(); - this.resolveTokenSource = null; + activate() { + if (this._isActive) + return; + this._isActive = true; + this.nvim.call('coc#snippet#enable', [], true); + } + deactivate() { + if (this._isActive) { + this._isActive = false; + this._snippet = null; + this.nvim.call('coc#snippet#disable', [], true); + logger.debug("[SnippetManager::cancel]"); } + this._onCancelEvent.fire(void 0); + this._onCancelEvent.dispose(); } - stop() { - let { nvim } = this; - if (!this.activated) + get isActive() { + return this._isActive; + } + async nextPlaceholder() { + await this.documentSynchronize(); + if (!this.isActive) + return; + let curr = this.placeholder; + let next = this.snippet.getNextPlaceholder(curr.index); + await this.selectPlaceholder(next); + } + async previousPlaceholder() { + await this.documentSynchronize(); + if (!this.isActive) + return; + let curr = this.placeholder; + let prev = this.snippet.getPrevPlaceholder(curr.index); + await this.selectPlaceholder(prev); + } + async synchronizeUpdatedPlaceholders(change) { + if (!this.isActive || !this.document || this.document.version - this.version == 1) + return; + if (!('range' in change)) + return; + let edit = { range: change.range, newText: change.text }; + let { snippet } = this; + // change outside range + let adjusted = snippet.adjustTextEdit(edit); + if (adjusted) + return; + if (position_1.comparePosition(edit.range.start, snippet.range.end) > 0) { + if (!edit.newText) + return; + logger.info('Content change after snippet, cancelling snippet session'); + this.deactivate(); return; - this.cancel(); - this.currItem = null; - this.activated = false; - this.document.paused = false; - this.document.fireContentChanges(); - if (this.complete) { - this.complete.dispose(); - this.complete = null; } - nvim.pauseNotification(); - if (this.config.numberSelect) { - nvim.call('coc#_unmap', [], true); + let placeholder = this.findPlaceholder(edit.range); + if (!placeholder) { + logger.info('Change outside placeholder, cancelling snippet session'); + this.deactivate(); + return; } - if (!this.config.keepCompleteopt) { - this.nvim.command(`noa set completeopt=${workspace_1.default.completeOpt}`, true); + if (placeholder.isFinalTabstop) { + logger.info('Change final placeholder, cancelling snippet session'); + this.deactivate(); + return; + } + this._currId = placeholder.id; + let { edits, delta } = snippet.updatePlaceholder(placeholder, edit); + if (!edits.length) + return; + this.version = this.document.version; + // let pos = await workspace.getCursorPosition() + await this.document.applyEdits(this.nvim, edits); + if (delta) { + await this.nvim.call('coc#util#move_cursor', delta); } - nvim.command(`let g:coc#_context['candidates'] = []`, true); - nvim.call('coc#_hide', [], true); - nvim.resumeNotification(false, true).catch(_e => { - // noop - }); } - getInput(document, pre) { - let input = ''; - for (let i = pre.length - 1; i >= 0; i--) { - let ch = i == 0 ? null : pre[i - 1]; - if (!ch || !document.isWord(ch)) { - input = pre.slice(i, pre.length); - break; + async selectCurrentPlaceholder(triggerAutocmd = true) { + let placeholder = this.snippet.getPlaceholderById(this._currId); + if (placeholder) + await this.selectPlaceholder(placeholder, triggerAutocmd); + } + async selectPlaceholder(placeholder, triggerAutocmd = true) { + let { nvim, document } = this; + if (!document || !placeholder) + return; + let { start, end } = placeholder.range; + const len = end.character - start.character; + const col = string_1.byteLength(document.getline(start.line).slice(0, start.character)) + 1; + this._currId = placeholder.id; + if (placeholder.choice) { + await nvim.call('coc#snippet#show_choices', [start.line + 1, col, len, placeholder.choice]); + } + else { + await this.select(placeholder.range, placeholder.value, triggerAutocmd); + } + } + async select(range, text, triggerAutocmd = true) { + let { document, nvim } = this; + let { start, end } = range; + let { textDocument } = document; + let len = textDocument.offsetAt(end) - textDocument.offsetAt(start); + let line = document.getline(start.line); + let col = line ? string_1.byteLength(line.slice(0, start.character)) : 0; + let endLine = document.getline(end.line); + let endCol = endLine ? string_1.byteLength(endLine.slice(0, end.character)) : 0; + nvim.setVar('coc_last_placeholder', { + current_text: text, + start: { line: start.line, col }, + end: { line: end.line, col: endCol } + }, true); + let [ve, selection, pumvisible, mode] = await nvim.eval('[&virtualedit, &selection, pumvisible(), mode()]'); + let move_cmd = ''; + if (pumvisible && this.preferComplete) { + let pre = completion_1.default.hasSelected() ? '' : '\\'; + await nvim.eval(`feedkeys("${pre}\\", 'in')`); + return; + } + let resetVirtualEdit = false; + if (mode != 'n') + move_cmd += "\\"; + if (len == 0) { + if (col == 0 || (!mode.startsWith('i') && col < string_1.byteLength(line))) { + move_cmd += 'i'; + } + else { + move_cmd += 'a'; } } - return input; + else { + move_cmd += 'v'; + endCol = await this.getVirtualCol(end.line + 1, endCol); + if (selection == 'inclusive') { + if (end.character == 0) { + move_cmd += `${end.line}G`; + } + else { + move_cmd += `${end.line + 1}G${endCol}|`; + } + } + else if (selection == 'old') { + move_cmd += `${end.line + 1}G${endCol}|`; + } + else { + move_cmd += `${end.line + 1}G${endCol + 1}|`; + } + col = await this.getVirtualCol(start.line + 1, col); + move_cmd += `o${start.line + 1}G${col + 1}|o\\`; + } + nvim.pauseNotification(); + if (ve != 'onemore') { + resetVirtualEdit = true; + nvim.setOption('virtualedit', 'onemore', true); + } + nvim.command(`noa call cursor(${start.line + 1},${col + (move_cmd == 'a' ? 0 : 1)})`, true); + nvim.call('eval', [`feedkeys("${move_cmd}", 'in')`], true); + if (resetVirtualEdit) + nvim.setOption('virtualedit', ve, true); + if (workspace_1.default.env.isVim) + nvim.command('redraw', true); + await nvim.resumeNotification(); + if (triggerAutocmd) + nvim.command('silent doautocmd User CocJumpPlaceholder', true); } - get completeOpt() { - let { noselect, enablePreview } = this.config; - let preview = enablePreview && !workspace_1.default.env.pumevent ? ',preview' : ''; - if (noselect) - return `noselect,menuone${preview}`; - return `noinsert,menuone${preview}`; + async getVirtualCol(line, col) { + let { nvim } = this; + return await nvim.eval(`virtcol([${line}, ${col}])`); } - getCompleteItem(item) { - if (!this.isActivated) + async documentSynchronize() { + if (!this.isActive) + return; + await this.document.patchChange(); + this.document.forceSync(); + await util_1.wait(50); + } + async checkPosition() { + if (!this.isActive) + return; + let position = await workspace_1.default.getCursorPosition(); + if (this.snippet && position_1.positionInRange(position, this.snippet.range) != 0) { + logger.info('Cursor insert out of range, cancelling snippet session'); + this.deactivate(); + } + } + findPlaceholder(range) { + if (!this.snippet) return null; - return this.complete.resolveCompletionItem(item); + let { placeholder } = this; + if (position_1.rangeInRange(range, placeholder.range)) + return placeholder; + return this.snippet.getPlaceholderByRange(range) || null; } - dispose() { - util_1.disposeAll(this.disposables); + get placeholder() { + if (!this.snippet) + return; + return this.snippet.getPlaceholderById(this._currId); + } + get snippet() { + return this._snippet; + } + get document() { + return workspace_1.default.getDocument(this.bufnr); } } -exports.Completion = Completion; -exports.default = new Completion(); -//# sourceMappingURL=index.js.map +exports.SnippetSession = SnippetSession; +function normalizeSnippetString(snippet, indent, opts) { + let lines = snippet.split(/\r?\n/); + let ind = opts.insertSpaces ? ' '.repeat(opts.tabSize) : '\t'; + let tabSize = opts.tabSize || 2; + lines = lines.map((line, idx) => { + let space = line.match(/^\s*/)[0]; + let pre = space; + let isTab = space.startsWith('\t'); + if (isTab && opts.insertSpaces) { + pre = ind.repeat(space.length); + } + else if (!isTab && !opts.insertSpaces) { + pre = ind.repeat(space.length / tabSize); + } + return (idx == 0 || line.length == 0 ? '' : indent) + pre + line.slice(space.length); + }); + return lines.join('\n'); +} +exports.normalizeSnippetString = normalizeSnippetString; +//# sourceMappingURL=session.js.map /***/ }), -/* 252 */ +/* 253 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); -const fast_diff_1 = tslib_1.__importDefault(__webpack_require__(212)); -const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); -const path_1 = tslib_1.__importDefault(__webpack_require__(20)); -const util_1 = tslib_1.__importDefault(__webpack_require__(12)); +const debounce_1 = tslib_1.__importDefault(__webpack_require__(179)); const vscode_languageserver_protocol_1 = __webpack_require__(150); const events_1 = tslib_1.__importDefault(__webpack_require__(149)); -const extensions_1 = tslib_1.__importDefault(__webpack_require__(253)); -const source_1 = tslib_1.__importDefault(__webpack_require__(395)); -const source_vim_1 = tslib_1.__importDefault(__webpack_require__(396)); -const types_1 = __webpack_require__(192); -const util_2 = __webpack_require__(177); -const fs_2 = __webpack_require__(203); -const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); +const sources_1 = tslib_1.__importDefault(__webpack_require__(254)); +const util_1 = __webpack_require__(177); const string_1 = __webpack_require__(213); -const logger = __webpack_require__(2)('sources'); -class Sources { +const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); +const complete_1 = tslib_1.__importDefault(__webpack_require__(395)); +const floating_1 = tslib_1.__importDefault(__webpack_require__(397)); +const logger = __webpack_require__(2)('completion'); +const completeItemKeys = ['abbr', 'menu', 'info', 'kind', 'icase', 'dup', 'empty', 'user_data']; +class Completion { constructor() { - this.sourceMap = new Map(); + // current input string + this.activated = false; this.disposables = []; - this.remoteSourcePaths = []; + this.complete = null; + this.recentScores = {}; + this.changedTick = 0; + this.insertCharTs = 0; + this.insertLeaveTs = 0; + // only used when no pum change event + this.isResolving = false; + } + init() { + this.config = this.getCompleteConfig(); + this.floating = new floating_1.default(); + events_1.default.on('InsertCharPre', this.onInsertCharPre, this, this.disposables); + events_1.default.on('InsertLeave', this.onInsertLeave, this, this.disposables); + events_1.default.on('InsertEnter', this.onInsertEnter, this, this.disposables); + events_1.default.on('TextChangedP', this.onTextChangedP, this, this.disposables); + events_1.default.on('TextChangedI', this.onTextChangedI, this, this.disposables); + events_1.default.on('CompleteDone', this.onCompleteDone, this, this.disposables); + events_1.default.on('MenuPopupChanged', this.onPumChange, this, this.disposables); + events_1.default.on('CursorMovedI', debounce_1.default(async (bufnr, cursor) => { + // try trigger completion + let doc = workspace_1.default.getDocument(bufnr); + if (this.isActivated || !doc || cursor[1] == 1 || !this.latestInsertChar) + return; + let line = doc.getline(cursor[0] - 1); + if (!line) + return; + let pre = string_1.byteSlice(line, 0, cursor[1] - 1); + if (sources_1.default.shouldTrigger(pre, doc.filetype)) { + await this.triggerCompletion(doc, pre, false); + } + }, 50)); + workspace_1.default.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('suggest')) { + Object.assign(this.config, this.getCompleteConfig()); + } + }, null, this.disposables); } get nvim() { return workspace_1.default.nvim; } - async createNativeSources() { - try { - this.disposables.push((__webpack_require__(397)).regist(this.sourceMap)); - this.disposables.push((__webpack_require__(398)).regist(this.sourceMap)); - this.disposables.push((__webpack_require__(399)).regist(this.sourceMap)); - } - catch (e) { - console.error('Create source error:' + e.message); // tslint:disable-line - } + get option() { + if (!this.complete) + return null; + return this.complete.option; } - async createVimSourceExtension(nvim, filepath) { - let name = path_1.default.basename(filepath, '.vim'); - try { - await nvim.command(`source ${filepath}`); - let fns = await nvim.call('coc#util#remote_fns', name); - for (let fn of ['init', 'complete']) { - if (fns.indexOf(fn) == -1) { - workspace_1.default.showMessage(`${fn} not found for source ${name}`, 'error'); - return null; - } - } - let props = await nvim.call(`coc#source#${name}#init`, []); - let packageJSON = { - name: `coc-source-${name}`, - engines: { - coc: ">= 0.0.1" - }, - activationEvents: props.filetypes ? props.filetypes.map(f => `onLanguage:${f}`) : ['*'], - contributes: { - configuration: { - properties: { - [`coc.source.${name}.enable`]: { - type: 'boolean', - default: true - }, - [`coc.source.${name}.firstMatch`]: { - type: 'boolean', - default: !!props.firstMatch - }, - [`coc.source.${name}.triggerCharacters`]: { - type: 'number', - default: props.triggerCharacters || [] - }, - [`coc.source.${name}.priority`]: { - type: 'number', - default: props.priority || 9 - }, - [`coc.source.${name}.shortcut`]: { - type: 'string', - default: props.shortcut || name.slice(0, 3).toUpperCase(), - description: 'Shortcut text shown in complete menu.' - }, - [`coc.source.${name}.disableSyntaxes`]: { - type: 'array', - default: [], - items: { - type: 'string' - } - }, - [`coc.source.${name}.filetypes`]: { - type: 'array', - default: props.filetypes || null, - description: 'Enabled filetypes.', - items: { - type: 'string' - } - } - } - } - } - }; - let source = new source_vim_1.default({ - name, - filepath, - sourceType: types_1.SourceType.Remote, - optionalFns: fns.filter(n => ['init', 'complete'].indexOf(n) == -1) - }); - let isActive = false; - let extension = { - id: packageJSON.name, - packageJSON, - exports: void 0, - extensionPath: filepath, - activate: async () => { - isActive = true; - this.addSource(source); - } - }; - Object.defineProperty(extension, 'isActive', { - get: () => { - return isActive; - } - }); - extensions_1.default.registerExtension(extension, () => { - isActive = false; - this.removeSource(source); - }); - } - catch (e) { - workspace_1.default.showMessage(`Error on create vim source ${name}: ${e.message}`, 'error'); - } - } - async createRemoteSources() { - let { runtimepath } = workspace_1.default.env; - let paths = runtimepath.split(','); - for (let path of paths) { - await this.createVimSources(path); - } - } - async createVimSources(pluginPath) { - if (this.remoteSourcePaths.indexOf(pluginPath) != -1) + addRecent(word, bufnr) { + if (!word) return; - this.remoteSourcePaths.push(pluginPath); - let folder = path_1.default.join(pluginPath, 'autoload/coc/source'); - let stat = await fs_2.statAsync(folder); - if (stat && stat.isDirectory()) { - let arr = await util_1.default.promisify(fs_1.default.readdir)(folder); - arr = arr.filter(s => s.slice(-4) == '.vim'); - let files = arr.map(s => path_1.default.join(folder, s)); - if (files.length == 0) - return; - await Promise.all(files.map(p => { - return this.createVimSourceExtension(this.nvim, p); - })); - } - } - init() { - this.createNativeSources(); // tslint:disable-line - this.createRemoteSources(); // tslint:disable-line - events_1.default.on('BufEnter', this.onDocumentEnter, this, this.disposables); - 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) { - if (p) - await this.createVimSources(p); - } - } - } - }, this.disposables); + this.recentScores[`${bufnr}|${word}`] = Date.now(); } - get names() { - return Array.from(this.sourceMap.keys()); + async getPreviousContent(document) { + let [, lnum, col] = await this.nvim.call('getcurpos'); + if (this.option && lnum != this.option.linenr) + return null; + let line = document.getline(lnum - 1); + return col == 1 ? '' : string_1.byteSlice(line, 0, col - 1); } - get sources() { - return Array.from(this.sourceMap.values()); + getResumeInput(pre) { + let { option, activated } = this; + if (!activated) + return null; + if (!pre) + return ''; + let input = string_1.byteSlice(pre, option.col); + if (option.blacklist && option.blacklist.indexOf(input) !== -1) + return null; + return input; } - has(name) { - return this.names.findIndex(o => o == name) != -1; + get bufnr() { + let { option } = this; + return option ? option.bufnr : null; } - getSource(name) { - if (!name) - return null; - return this.sourceMap.get(name) || null; + get isActivated() { + return this.activated; } - async doCompleteResolve(item, token) { - let source = this.getSource(item.source); - if (source && typeof source.onCompleteResolve == 'function') { - try { - await Promise.resolve(source.onCompleteResolve(item, token)); - } - catch (e) { - logger.error('Error on complete resolve:', e.stack); + getCompleteConfig() { + let config = workspace_1.default.getConfiguration('coc.preferences'); + let suggest = workspace_1.default.getConfiguration('suggest'); + function getConfig(key, defaultValue) { + return config.get(key, suggest.get(key, defaultValue)); + } + let keepCompleteopt = getConfig('keepCompleteopt', false); + let autoTrigger = getConfig('autoTrigger', 'always'); + if (keepCompleteopt) { + let { completeOpt } = workspace_1.default; + if (!completeOpt.includes('noinsert') && !completeOpt.includes('noselect')) { + autoTrigger = 'none'; } } + let acceptSuggestionOnCommitCharacter = workspace_1.default.env.pumevent && getConfig('acceptSuggestionOnCommitCharacter', false); + return { + autoTrigger, + keepCompleteopt, + defaultSortMethod: getConfig('defaultSortMethod', 'length'), + removeDuplicateItems: getConfig('removeDuplicateItems', false), + disableMenuShortcut: getConfig('disableMenuShortcut', false), + acceptSuggestionOnCommitCharacter, + disableKind: getConfig('disableKind', false), + disableMenu: getConfig('disableMenu', false), + previewIsKeyword: getConfig('previewIsKeyword', '@,48-57,_192-255'), + enablePreview: getConfig('enablePreview', false), + enablePreselect: getConfig('enablePreselect', false), + maxPreviewWidth: getConfig('maxPreviewWidth', 80), + labelMaxLength: getConfig('labelMaxLength', 200), + triggerAfterInsertEnter: getConfig('triggerAfterInsertEnter', false), + noselect: getConfig('noselect', true), + numberSelect: getConfig('numberSelect', false), + maxItemCount: getConfig('maxCompleteItemCount', 50), + timeout: getConfig('timeout', 500), + minTriggerInputLength: getConfig('minTriggerInputLength', 1), + snippetIndicator: getConfig('snippetIndicator', '~'), + fixInsertedWord: getConfig('fixInsertedWord', true), + localityBonus: getConfig('localityBonus', true), + highPrioritySourceLimit: getConfig('highPrioritySourceLimit', null), + lowPrioritySourceLimit: getConfig('lowPrioritySourceLimit', null), + asciiCharactersOnly: getConfig('asciiCharactersOnly', false) + }; } - async doCompleteDone(item, opt) { - let data = JSON.parse(item.user_data); - let source = this.getSource(data.source); - if (source && typeof source.onCompleteDone === 'function') { - await Promise.resolve(source.onCompleteDone(item, opt)); + async startCompletion(option) { + workspace_1.default.bufnr = option.bufnr; + let document = workspace_1.default.getDocument(option.bufnr); + if (!document) + return; + // use fixed filetype + option.filetype = document.filetype; + this.document = document; + try { + await this._doComplete(option); } - } - shouldCommit(item, commitCharacter) { - if (!item || !item.source) - return false; - let source = this.getSource(item.source); - if (source && source.sourceType == types_1.SourceType.Service && typeof source.shouldCommit === 'function') { - return source.shouldCommit(item, commitCharacter); + catch (e) { + this.stop(); + workspace_1.default.showMessage(`Error happens on complete: ${e.message}`, 'error'); + logger.error(e.stack); } - return false; - } - getCompleteSources(opt) { - let { filetype } = opt; - let pre = string_1.byteSlice(opt.line, 0, opt.colnr - 1); - let isTriggered = opt.input == '' && opt.triggerCharacter; - if (isTriggered) - return this.getTriggerSources(pre, filetype); - let character = pre.length ? pre[pre.length - 1] : ''; - return this.sources.filter(source => { - let { filetypes, triggerOnly, enable } = source; - if (!enable || (filetypes && filetypes.indexOf(filetype) == -1)) { - return false; - } - if (triggerOnly && !this.checkTrigger(source, pre, character)) { - return false; - } - return true; - }); } - checkTrigger(source, pre, character) { - let { triggerCharacters, triggerPatterns } = source; - if (!triggerCharacters && !triggerPatterns) - return false; - if (character && triggerCharacters && triggerCharacters.indexOf(character) !== -1) { - return true; + async resumeCompletion(pre, search, force = false) { + let { document, complete, activated } = this; + if (!activated || !complete.results) + return; + if (search == this.input && !force) + return; + let last = search == null ? '' : search.slice(-1); + if (last.length == 0 || + /\s/.test(last) || + sources_1.default.shouldTrigger(pre, document.filetype) || + search.length < complete.input.length) { + this.stop(); + return; } - if (triggerPatterns && triggerPatterns.findIndex(p => p.test(pre)) !== -1) { - return true; + this.input = search; + let items; + if (complete.isIncomplete && document.chars.isKeywordChar(last)) { + await document.patchChange(); + document.forceSync(); + await util_1.wait(30); + items = await complete.completeInComplete(search); + // check search change + let content = await this.getPreviousContent(document); + let curr = this.getResumeInput(content); + if (curr != search) + return; } - return false; - } - shouldTrigger(pre, languageId) { - let last = pre.length ? pre[pre.length - 1] : ''; - let idx = this.sources.findIndex(s => { - let { enable, triggerCharacters, triggerPatterns, filetypes } = s; - if (!enable || (filetypes && filetypes.indexOf(languageId) == -1)) - return false; - if (last && triggerCharacters) - return triggerCharacters.indexOf(last) !== -1; - if (triggerPatterns) - return triggerPatterns.findIndex(p => p.test(pre)) !== -1; - return false; - }); - return idx !== -1; + else { + items = complete.filterResults(search); + } + if (!this.isActivated) + return; + if (!complete.isCompleting && (!items || items.length === 0)) { + this.stop(); + return; + } + await this.showCompletion(this.option.col, items); } - getTriggerSources(pre, languageId) { - let character = pre.length ? pre[pre.length - 1] : ''; - return this.sources.filter(source => { - let { filetypes, enable } = source; - if (!enable || (filetypes && filetypes.indexOf(languageId) == -1)) { - return false; - } - return this.checkTrigger(source, pre, character); - }); + hasSelected() { + if (workspace_1.default.env.pumevent) + return this.currItem != null; + if (this.config.noselect === false) + return true; + return this.isResolving; } - getSourcesForFiletype(filetype, isTriggered) { - return this.sources.filter(source => { - let { filetypes } = source; - if (source.triggerOnly && isTriggered === false) { - return false; - } - if (source.enable && (!filetypes || filetypes.indexOf(filetype) !== -1)) { - return true; + async showCompletion(col, items) { + let { nvim, document, option } = this; + let { numberSelect, disableKind, labelMaxLength, disableMenuShortcut, disableMenu } = this.config; + let preselect = this.config.enablePreselect ? items.findIndex(o => o.preselect == true) : -1; + if (numberSelect && option.input.length && !/^\d/.test(option.input)) { + items = items.map((item, i) => { + let idx = i + 1; + if (i < 9) { + return Object.assign({}, item, { + abbr: item.abbr ? `${idx} ${item.abbr}` : `${idx} ${item.word}` + }); + } + return item; + }); + nvim.call('coc#_map', [], true); + } + this.changedTick = document.changedtick; + let validKeys = completeItemKeys.slice(); + if (disableKind) + validKeys = validKeys.filter(s => s != 'kind'); + if (disableMenu) + validKeys = validKeys.filter(s => s != 'menu'); + let vimItems = items.map(item => { + let obj = { word: item.word, equal: 1 }; + for (let key of validKeys) { + if (item.hasOwnProperty(key)) { + if (disableMenuShortcut && key == 'menu') { + obj[key] = item[key].replace(/\[\w+\]$/, ''); + } + else if (key == 'abbr' && item[key].length > labelMaxLength) { + obj[key] = item[key].slice(0, labelMaxLength); + } + else { + obj[key] = item[key]; + } + } } - return false; + return obj; }); + nvim.call('coc#_do_complete', [col, vimItems, preselect], true); } - addSource(source) { - let { name } = source; - if (this.names.indexOf(name) !== -1) { - workspace_1.default.showMessage(`Source "${name}" recreated`, 'warning'); + async _doComplete(option) { + let { source } = option; + let { nvim, config, document } = this; + // current input + this.input = option.input; + let arr = []; + if (source == null) { + arr = sources_1.default.getCompleteSources(option); } - this.sourceMap.set(name, source); - return vscode_languageserver_protocol_1.Disposable.create(() => { - this.sourceMap.delete(name); - }); - } - removeSource(source) { - let name = typeof source == 'string' ? source : source.name; - if (source == this.sourceMap.get(name)) { - this.sourceMap.delete(name); + else { + let s = sources_1.default.getSource(source); + if (s) + arr.push(s); } - } - async refresh(name) { - for (let source of this.sources) { - if (!name || source.name == name) { - if (typeof source.refresh === 'function') { - await Promise.resolve(source.refresh()); - } + if (!arr.length) + return; + let complete = new complete_1.default(option, document, this.recentScores, config, arr, nvim); + this.start(complete); + let items = await this.complete.doComplete(); + if (complete.isCanceled) + return; + if (items.length == 0 && !complete.isCompleting) { + this.stop(); + return; + } + complete.onDidComplete(async () => { + let content = await this.getPreviousContent(document); + let search = this.getResumeInput(content); + if (complete.isCanceled) + return; + let hasSelected = this.hasSelected(); + if (hasSelected && this.completeOpt.indexOf('noselect') !== -1) + return; + if (search == this.option.input) { + let items = complete.filterResults(search, Math.floor(Date.now() / 1000)); + await this.showCompletion(option.col, items); + return; + } + await this.resumeCompletion(content, search, true); + }); + if (items.length) { + let content = await this.getPreviousContent(document); + let search = this.getResumeInput(content); + if (complete.isCanceled) + return; + if (search == this.option.input) { + await this.showCompletion(option.col, items); + return; } + await this.resumeCompletion(content, search, true); } } - toggleSource(name) { - if (!name) + async onTextChangedP() { + let { option, document } = this; + if (!option) return; - let source = this.getSource(name); - if (!source) + await document.patchChange(); + let hasInsert = this.latestInsert != null; + this.lastInsert = null; + // avoid trigger filter on pumvisible + if (document.changedtick == this.changedTick) + return; + let line = document.getline(option.linenr - 1); + let curr = line.match(/^\s*/)[0]; + let ind = option.line.match(/^\s*/)[0]; + // indent change + if (ind.length != curr.length) { + this.stop(); return; - if (typeof source.toggle === 'function') { - source.toggle(); } - } - sourceStats() { - let res = []; - let items = this.sources; - for (let item of items) { - res.push({ - name: item.name, - priority: item.priority, - shortcut: item.shortcut || '', - filetypes: item.filetypes || [], - filepath: item.filepath || '', - type: item.sourceType == types_1.SourceType.Native - ? 'native' : item.sourceType == types_1.SourceType.Remote - ? 'remote' : 'service', - disabled: !item.enable - }); + if (!hasInsert) { + // this could be wrong, but can't avoid. + this.isResolving = true; + return; } - return res; - } - onDocumentEnter(bufnr) { - let { sources } = this; - for (let s of sources) { - if (!s.enable) - continue; - if (typeof s.onEnter == 'function') { - s.onEnter(bufnr); - } + let pre = await this.getPreviousContent(document); + if (!pre) + return; + let search = this.getResumeInput(pre); + if (sources_1.default.shouldTrigger(pre, document.filetype)) { + await this.triggerCompletion(document, pre, false); + } + else { + await this.resumeCompletion(pre, search); } } - createSource(config) { - if (!config.name || !config.doComplete) { - // tslint:disable-next-line: no-console - console.error(`name and doComplete required for createSource`); + async onTextChangedI(bufnr) { + let { nvim, latestInsertChar } = this; + this.lastInsert = null; + let document = workspace_1.default.getDocument(workspace_1.default.bufnr); + if (!document) + return; + await document.patchChange(); + if (!this.isActivated) { + if (!latestInsertChar) + return; + let pre = await this.getPreviousContent(document); + await this.triggerCompletion(document, pre); return; } - let source = new source_1.default(Object.assign({ sourceType: types_1.SourceType.Service }, config)); - return this.addSource(source); - } - dispose() { - util_2.disposeAll(this.disposables); - } -} -exports.Sources = Sources; -exports.default = new Sources(); -//# sourceMappingURL=sources.js.map - -/***/ }), -/* 253 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const tslib_1 = __webpack_require__(3); -const debounce_1 = __webpack_require__(179); -const fast_diff_1 = tslib_1.__importDefault(__webpack_require__(212)); -const os_1 = tslib_1.__importDefault(__webpack_require__(14)); -const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); -const isuri_1 = tslib_1.__importDefault(__webpack_require__(180)); -const path_1 = tslib_1.__importDefault(__webpack_require__(20)); -const rimraf_1 = tslib_1.__importDefault(__webpack_require__(234)); -const semver_1 = tslib_1.__importDefault(__webpack_require__(1)); -const util_1 = __webpack_require__(12); -const vscode_languageserver_protocol_1 = __webpack_require__(150); -const vscode_uri_1 = __webpack_require__(183); -const which_1 = tslib_1.__importDefault(__webpack_require__(184)); -const commands_1 = tslib_1.__importDefault(__webpack_require__(247)); -const events_1 = tslib_1.__importDefault(__webpack_require__(149)); -const db_1 = tslib_1.__importDefault(__webpack_require__(209)); -const extension_1 = tslib_1.__importDefault(__webpack_require__(254)); -const memos_1 = tslib_1.__importDefault(__webpack_require__(311)); -const util_2 = __webpack_require__(177); -const mkdirp_1 = tslib_1.__importDefault(__webpack_require__(182)); -const array_1 = __webpack_require__(215); -__webpack_require__(312); -const factory_1 = __webpack_require__(313); -const fs_2 = __webpack_require__(203); -const watchman_1 = tslib_1.__importDefault(__webpack_require__(230)); -const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const createLogger = __webpack_require__(2); -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() { - 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'); - 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) + if (bufnr !== this.bufnr) 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) { - if (p) - await this.loadExtension(p, true); - } - } - } - }); - commands_1.default.register({ - id: 'extensions.forceUpdateAll', - execute: async () => { - await this.cleanExtensions(); - await this.installExtensions([]); + // check commit character + if (this.config.acceptSuggestionOnCommitCharacter + && this.currItem + && latestInsertChar + && !this.document.isWord(latestInsertChar)) { + let resolvedItem = this.getCompleteItem(this.currItem); + if (sources_1.default.shouldCommit(resolvedItem, latestInsertChar)) { + let { linenr, col, line, colnr } = this.option; + this.stop(); + let { word } = resolvedItem; + let newLine = `${line.slice(0, col)}${word}${latestInsertChar}${line.slice(colnr - 1)}`; + await nvim.call('coc#util#setline', [linenr, newLine]); + let curcol = col + word.length + 2; + await nvim.call('cursor', [linenr, curcol]); + return; } - }); - } - async activateExtensions() { - this.activated = true; - if (global.hasOwnProperty('__TEST__')) + } + let content = await this.getPreviousContent(document); + if (content == null) { + // cursor line changed + this.stop(); 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(); + // check trigger character + if (sources_1.default.shouldTrigger(content, document.filetype)) { + await this.triggerCompletion(document, content, false); + return; } - } - async updateExtensions() { - if (!this.root) - await this.initializeRoot(); - if (!this.npm) + if (!this.isActivated || this.complete.isEmpty) return; - let lockedList = await this.getLockedList(); - let stats = await this.globalExtensionStats(); - 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(); - this.db.push('lastUpdate', Date.now()); - await util_2.concurrent(names.map(name => { - let o = stats.find(o => o.id == name); - return () => { - 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}`); - }); - }; - }), 5); - workspace_1.default.showMessage('Update completed', 'more'); - statusItem.dispose(); + let search = content.slice(string_1.characterIndex(content, this.option.col)); + return await this.resumeCompletion(content, search); } - 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.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) + async triggerCompletion(document, pre, checkTrigger = true) { + // check trigger + if (checkTrigger) { + let shouldTrigger = await this.shouldTrigger(document, pre); + if (!shouldTrigger) 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.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) + let option = await this.nvim.call('coc#util#get_complete_option'); + if (!option) 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(); + this.fixCompleteOption(option); + option.triggerCharacter = pre.slice(-1); + logger.debug('trigger completion with', option); + await this.startCompletion(option); } - /** - * 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); + fixCompleteOption(opt) { + if (workspace_1.default.isVim) { + for (let key of ['word', 'input', 'line', 'filetype']) { + if (opt[key] == null) { + opt[key] = ''; } } } - return ids; } - get npm() { - let npm = workspace_1.default.getConfiguration('npm').get('binPath', 'npm'); - if (npm.startsWith('~')) { - npm = os_1.default.homedir() + npm.slice(1); + async onCompleteDone(item) { + let { document } = this; + if (!this.isActivated || !document || !item.hasOwnProperty('word')) + return; + let visible = await this.nvim.call('pumvisible'); + if (visible) + return; + let opt = Object.assign({}, this.option); + let resolvedItem = this.getCompleteItem(item); + this.stop(); + if (!resolvedItem) + return; + let timestamp = this.insertCharTs; + let insertLeaveTs = this.insertLeaveTs; + try { + await sources_1.default.doCompleteResolve(resolvedItem, (new vscode_languageserver_protocol_1.CancellationTokenSource()).token); + this.addRecent(resolvedItem.word, document.bufnr); + await util_1.wait(50); + if (this.insertCharTs != timestamp + || this.insertLeaveTs != insertLeaveTs) + return; + await document.patchChange(); + let content = await this.getPreviousContent(document); + if (!content.endsWith(resolvedItem.word)) + return; + await sources_1.default.doCompleteDone(resolvedItem, opt); + document.forceSync(); } - for (let exe of [npm, 'yarnpkg', 'yarn', 'npm']) { - try { - let res = which_1.default.sync(exe); - return res; - } - catch (e) { - continue; - } + catch (e) { + // tslint:disable-next-line:no-console + console.error(e.stack); + logger.error(`error on complete done`, e.stack); } - 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); + async onInsertLeave(bufnr) { + this.insertLeaveTs = Date.now(); + if (this.isActivated) { + let doc = workspace_1.default.getDocument(bufnr); + if (doc) + doc.forceSync(); + this.stop(); + } } - getExtension(id) { - return this.list.find(o => o.id == id); + async onInsertEnter(bufnr) { + if (!this.config.triggerAfterInsertEnter) + return; + let document = workspace_1.default.getDocument(bufnr); + if (!document) + return; + await document.patchChange(); + if (!document) + return; + let cursor = await this.nvim.call('coc#util#cursor'); + let line = document.getline(cursor[0]); + let pre = string_1.byteSlice(line, 0, cursor[1]); + if (!pre) + return; + await this.triggerCompletion(document, pre, false); } - 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 onInsertCharPre(character) { + this.lastInsert = { + character, + timestamp: Date.now(), + }; + this.insertCharTs = this.lastInsert.timestamp; } - async getExtensionStates() { - let globalStats = await this.globalExtensionStats(); - let localStats = await this.localExtensionStats(globalStats); - return globalStats.concat(localStats); + get latestInsert() { + let { lastInsert } = this; + if (!lastInsert || Date.now() - lastInsert.timestamp > 500) { + return null; + } + return lastInsert; } - async getLockedList() { - let obj = await this.db.fetch('extension'); - obj = obj || {}; - return Object.keys(obj).filter(id => { - return obj[id].locked === true; - }); + get latestInsertChar() { + let { latestInsert } = this; + if (!latestInsert) + return ''; + return latestInsert.character; } - 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 shouldTrigger(document, pre) { + if (pre.length == 0 || /\s/.test(pre[pre.length - 1])) + return false; + let autoTrigger = this.config.autoTrigger; + if (autoTrigger == 'none') + return false; + if (sources_1.default.shouldTrigger(pre, document.filetype)) + return true; + if (autoTrigger !== 'always') + return false; + let last = pre.slice(-1); + if (last && (document.isWord(pre.slice(-1)) || last.codePointAt(0) > 255)) { + let minLength = this.config.minTriggerInputLength; + if (minLength == 1) + return true; + let input = this.getInput(document, pre); + return input.length >= minLength; } + return false; } - async toggleExtension(id) { - let state = this.getExtensionState(id); - if (state == null) + async onPumChange(ev) { + if (!this.activated) + return; + if (this.document && this.document.uri.endsWith('%5BCommand%20Line%5D')) + return; + this.cancel(); + let { completed_item, col, row, height, width, scrollbar } = ev; + let bounding = { col, row, height, width, scrollbar }; + this.currItem = completed_item.hasOwnProperty('word') ? completed_item : null; + // it's pum change by vim, ignore it + if (this.lastInsert) + return; + let resolvedItem = this.getCompleteItem(completed_item); + if (!resolvedItem) { + this.floating.close(); 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); + let source = this.resolveTokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource(); + let { token } = source; + await sources_1.default.doCompleteResolve(resolvedItem, token); + if (token.isCancellationRequested) + return; + let docs = resolvedItem.documentation; + if (!docs && resolvedItem.info) { + let { info } = resolvedItem; + let isText = /^[\w-\s.,\t]+$/.test(info); + docs = [{ filetype: isText ? 'txt' : this.document.filetype, content: info }]; + } + if (!docs || docs.length == 0) { + this.floating.close(); } 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'); - } + if (token.isCancellationRequested) + return; + await this.floating.show(docs, bounding, token); } - await util_2.wait(200); + this.resolveTokenSource = null; } - 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); + start(complete) { + let { activated } = this; + this.activated = true; + this.isResolving = false; + if (activated) { + this.complete.dispose(); } - else { - this.activate(id); + this.complete = complete; + if (!this.config.keepCompleteopt) { + this.nvim.command(`noa set completeopt=${this.completeOpt}`, true); } + this.document.forceSync(true); + this.document.paused = true; } - /** - * 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 }); + cancel() { + if (this.resolveTokenSource) { + this.resolveTokenSource.cancel(); + this.resolveTokenSource = null; } } - async uninstallExtension(ids) { - if (!ids.length) + stop() { + let { nvim } = this; + if (!this.activated) 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.promisify(rimraf_1.default)(`${folder}`, { glob: false }); + this.cancel(); + this.currItem = null; + this.activated = false; + this.document.paused = false; + this.document.fireContentChanges(); + if (this.complete) { + this.complete.dispose(); + this.complete = null; + } + nvim.pauseNotification(); + if (this.config.numberSelect) { + nvim.call('coc#_unmap', [], true); + } + if (!this.config.keepCompleteopt) { + this.nvim.command(`noa set completeopt=${workspace_1.default.completeOpt}`, true); + } + nvim.command(`let g:coc#_context['candidates'] = []`, true); + nvim.call('coc#_hide', [], true); + nvim.resumeNotification(false, true).catch(_e => { + // noop + }); + } + getInput(document, pre) { + let input = ''; + for (let i = pre.length - 1; i >= 0; i--) { + let ch = i == 0 ? null : pre[i - 1]; + if (!ch || !document.isWord(ch)) { + input = pre.slice(i, pre.length); + break; + } + } + return input; + } + get completeOpt() { + let { noselect, enablePreview } = this.config; + let preview = enablePreview && !workspace_1.default.env.pumevent ? ',preview' : ''; + if (noselect) + return `noselect,menuone${preview}`; + return `noinsert,menuone${preview}`; + } + getCompleteItem(item) { + if (!this.isActivated) + return null; + return this.complete.resolveCompletionItem(item); + } + dispose() { + util_1.disposeAll(this.disposables); + } +} +exports.Completion = Completion; +exports.default = new Completion(); +//# sourceMappingURL=index.js.map + +/***/ }), +/* 254 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const tslib_1 = __webpack_require__(3); +const fast_diff_1 = tslib_1.__importDefault(__webpack_require__(212)); +const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); +const path_1 = tslib_1.__importDefault(__webpack_require__(20)); +const util_1 = tslib_1.__importDefault(__webpack_require__(12)); +const vscode_languageserver_protocol_1 = __webpack_require__(150); +const events_1 = tslib_1.__importDefault(__webpack_require__(149)); +const extensions_1 = tslib_1.__importDefault(__webpack_require__(255)); +const source_1 = tslib_1.__importDefault(__webpack_require__(390)); +const source_vim_1 = tslib_1.__importDefault(__webpack_require__(391)); +const types_1 = __webpack_require__(192); +const util_2 = __webpack_require__(177); +const fs_2 = __webpack_require__(203); +const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); +const string_1 = __webpack_require__(213); +const logger = __webpack_require__(2)('sources'); +class Sources { + constructor() { + this.sourceMap = new Map(); + this.disposables = []; + this.remoteSourcePaths = []; + } + get nvim() { + return workspace_1.default.nvim; + } + async createNativeSources() { + try { + this.disposables.push((__webpack_require__(392)).regist(this.sourceMap)); + this.disposables.push((__webpack_require__(393)).regist(this.sourceMap)); + this.disposables.push((__webpack_require__(394)).regist(this.sourceMap)); + } + catch (e) { + console.error('Create source error:' + e.message); // tslint:disable-line + } + } + async createVimSourceExtension(nvim, filepath) { + let name = path_1.default.basename(filepath, '.vim'); + try { + await nvim.command(`source ${filepath}`); + let fns = await nvim.call('coc#util#remote_fns', name); + for (let fn of ['init', 'complete']) { + if (fns.indexOf(fn) == -1) { + workspace_1.default.showMessage(`${fn} not found for source ${name}`, 'error'); + return null; } } - let jsonFile = path_1.default.join(this.root, 'package.json'); - status.dispose(); - const sortedObj = { dependencies: {} }; - Object.keys(json.dependencies).sort().forEach(k => { - sortedObj.dependencies[k] = json.dependencies[k]; + let props = await nvim.call(`coc#source#${name}#init`, []); + let packageJSON = { + name: `coc-source-${name}`, + engines: { + coc: ">= 0.0.1" + }, + activationEvents: props.filetypes ? props.filetypes.map(f => `onLanguage:${f}`) : ['*'], + contributes: { + configuration: { + properties: { + [`coc.source.${name}.enable`]: { + type: 'boolean', + default: true + }, + [`coc.source.${name}.firstMatch`]: { + type: 'boolean', + default: !!props.firstMatch + }, + [`coc.source.${name}.triggerCharacters`]: { + type: 'number', + default: props.triggerCharacters || [] + }, + [`coc.source.${name}.priority`]: { + type: 'number', + default: props.priority || 9 + }, + [`coc.source.${name}.shortcut`]: { + type: 'string', + default: props.shortcut || name.slice(0, 3).toUpperCase(), + description: 'Shortcut text shown in complete menu.' + }, + [`coc.source.${name}.disableSyntaxes`]: { + type: 'array', + default: [], + items: { + type: 'string' + } + }, + [`coc.source.${name}.filetypes`]: { + type: 'array', + default: props.filetypes || null, + description: 'Enabled filetypes.', + items: { + type: 'string' + } + } + } + } + } + }; + let source = new source_vim_1.default({ + name, + filepath, + sourceType: types_1.SourceType.Remote, + optionalFns: fns.filter(n => ['init', 'complete'].indexOf(n) == -1) + }); + let isActive = false; + let extension = { + id: packageJSON.name, + packageJSON, + exports: void 0, + extensionPath: filepath, + activate: async () => { + isActive = true; + this.addSource(source); + } + }; + Object.defineProperty(extension, 'isActive', { + get: () => { + return isActive; + } + }); + extensions_1.default.registerExtension(extension, () => { + isActive = false; + this.removeSource(source); }); - fs_1.default.writeFileSync(jsonFile, JSON.stringify(sortedObj, null, 2), { encoding: 'utf8' }); - workspace_1.default.showMessage(`Removed: ${ids.join(' ')}`); } catch (e) { - status.dispose(); - workspace_1.default.showMessage(`Uninstall failed: ${e.message}`, 'error'); + workspace_1.default.showMessage(`Error on create vim source ${name}: ${e.message}`, 'error'); } } - isDisabled(id) { - return this.disabled.has(id); + async createRemoteSources() { + let { runtimepath } = workspace_1.default.env; + let paths = runtimepath.split(','); + for (let path of paths) { + await this.createVimSources(path); + } } - async onExtensionInstall(id) { - if (!id) + async createVimSources(pluginPath) { + if (this.remoteSourcePaths.indexOf(pluginPath) != -1) 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); + this.remoteSourcePaths.push(pluginPath); + let folder = path_1.default.join(pluginPath, 'autoload/coc/source'); 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'))) + let arr = await util_1.default.promisify(fs_1.default.readdir)(folder); + arr = arr.filter(s => s.slice(-4) == '.vim'); + let files = arr.map(s => path_1.default.join(folder, s)); + if (files.length == 0) return; - await this.loadExtension(folder); + await Promise.all(files.map(p => { + return this.createVimSourceExtension(this.nvim, p); + })); } } - has(id) { - return this.list.find(o => o.id == id) != null; + init() { + this.createNativeSources(); // tslint:disable-line + this.createRemoteSources(); // tslint:disable-line + events_1.default.on('BufEnter', this.onDocumentEnter, this, this.disposables); + 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) { + if (p) + await this.createVimSources(p); + } + } + } + }, this.disposables); } - isActivated(id) { - let item = this.list.find(o => o.id == id); - if (item && item.extension.isActive) { - return true; - } - return false; + get names() { + return Array.from(this.sourceMap.keys()); } - 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.isActivated(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'); + get sources() { + return Array.from(this.sourceMap.values()); + } + has(name) { + return this.names.findIndex(o => o == name) != -1; + } + getSource(name) { + if (!name) + return null; + return this.sourceMap.get(name) || null; + } + async doCompleteResolve(item, token) { + let source = this.getSource(item.source); + if (source && typeof source.onCompleteResolve == 'function') { + try { + await Promise.resolve(source.onCompleteResolve(item, token)); + } + catch (e) { + logger.error('Error on complete resolve:', e.stack); } - 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 doCompleteDone(item, opt) { + let data = JSON.parse(item.user_data); + let source = this.getSource(data.source); + if (source && typeof source.onCompleteDone === 'function') { + await Promise.resolve(source.onCompleteDone(item, opt)); } } - async loadFileExtensions() { - if (!process.env.COC_VIMCONFIG) - return; - let folder = path_1.default.join(process.env.COC_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)); + shouldCommit(item, commitCharacter) { + if (!item || !item.source) + return false; + let source = this.getSource(item.source); + if (source && source.sourceType == types_1.SourceType.Service && typeof source.shouldCommit === 'function') { + return source.shouldCommit(item, commitCharacter); } + return false; } - /** - * 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); + getCompleteSources(opt) { + let { filetype } = opt; + let pre = string_1.byteSlice(opt.line, 0, opt.colnr - 1); + let isTriggered = opt.input == '' && opt.triggerCharacter; + if (isTriggered) + return this.getTriggerSources(pre, filetype); + let character = pre.length ? pre[pre.length - 1] : ''; + return this.sources.filter(source => { + let { filetypes, triggerOnly, enable } = source; + if (!enable || (filetypes && filetypes.indexOf(filetype) == -1)) { + return false; + } + if (triggerOnly && !this.checkTrigger(source, pre, character)) { + return false; + } + return true; + }); } - activate(id, silent = true) { - if (this.isDisabled(id)) { - if (!silent) - workspace_1.default.showMessage(`Extension ${id} is disabled!`, 'error'); - return; + checkTrigger(source, pre, character) { + let { triggerCharacters, triggerPatterns } = source; + if (!triggerCharacters && !triggerPatterns) + return false; + if (character && triggerCharacters && triggerCharacters.indexOf(character) !== -1) { + return true; } - let item = this.list.find(o => o.id == id); - if (!item) { - workspace_1.default.showMessage(`Extension ${id} not found!`, 'error'); - return; + if (triggerPatterns && triggerPatterns.findIndex(p => p.test(pre)) !== -1) { + return true; } - let { extension } = item; - if (extension.isActive) - return; - extension.activate().then(() => { - if (extension.isActive) { - this._onDidActiveExtension.fire(extension); + return false; + } + shouldTrigger(pre, languageId) { + let last = pre.length ? pre[pre.length - 1] : ''; + let idx = this.sources.findIndex(s => { + let { enable, triggerCharacters, triggerPatterns, filetypes } = s; + if (!enable || (filetypes && filetypes.indexOf(languageId) == -1)) + return false; + if (last && triggerCharacters) + return triggerCharacters.indexOf(last) !== -1; + if (triggerPatterns) + return triggerPatterns.findIndex(p => p.test(pre)) !== -1; + return false; + }); + return idx !== -1; + } + getTriggerSources(pre, languageId) { + let character = pre.length ? pre[pre.length - 1] : ''; + return this.sources.filter(source => { + let { filetypes, enable } = source; + if (!enable || (filetypes && filetypes.indexOf(languageId) == -1)) { + return false; } - }, e => { - workspace_1.default.showMessage(`Error on activate ${extension.id}: ${e.stack}`, 'error'); - logger.error(`Error on activate extension ${extension.id}:`, e); + return this.checkTrigger(source, pre, character); }); } - deactivate(id) { - let item = this.list.find(o => o.id == id); - if (!item) + getSourcesForFiletype(filetype, isTriggered) { + return this.sources.filter(source => { + let { filetypes } = source; + if (source.triggerOnly && isTriggered === false) { + return false; + } + if (source.enable && (!filetypes || filetypes.indexOf(filetype) !== -1)) { + return true; + } return false; - if (item.extension.isActive && typeof item.deactivate == 'function') { - item.deactivate(); - return true; + }); + } + addSource(source) { + let { name } = source; + if (this.names.indexOf(name) !== -1) { + workspace_1.default.showMessage(`Source "${name}" recreated`, 'warning'); } - return false; + this.sourceMap.set(name, source); + return vscode_languageserver_protocol_1.Disposable.create(() => { + this.sourceMap.delete(name); + }); } - 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; + removeSource(source) { + let name = typeof source == 'string' ? source : source.name; + if (source == this.sourceMap.get(name)) { + this.sourceMap.delete(name); } - let { exports } = extension; - if (!exports || !exports.hasOwnProperty(method)) { - workspace_1.default.showMessage(`method ${method} not found on extension ${id}`, 'error'); + } + async refresh(name) { + for (let source of this.sources) { + if (!name || source.name == name) { + if (typeof source.refresh === 'function') { + await Promise.resolve(source.refresh()); + } + } + } + } + toggleSource(name) { + if (!name) + return; + let source = this.getSource(name); + if (!source) return; + if (typeof source.toggle === 'function') { + source.toggle(); } - 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; + sourceStats() { + let res = []; + let items = this.sources; + for (let item of items) { + res.push({ + name: item.name, + priority: item.priority, + shortcut: item.shortcut || '', + filetypes: item.filetypes || [], + filepath: item.filepath || '', + type: item.sourceType == types_1.SourceType.Native + ? 'native' : item.sourceType == types_1.SourceType.Remote + ? 'remote' : 'service', + disabled: !item.enable + }); + } + return res; } - 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); + onDocumentEnter(bufnr) { + let { sources } = this; + for (let s of sources) { + if (!s.enable) + continue; + if (typeof s.onEnter == 'function') { + s.onEnter(bufnr); } } - this._onDidLoadExtension.fire(extension); - this.setupActiveEvents(id, packageJSON); } - get globalExtensions() { - let json = this.loadJson(); - if (!json || !json.dependencies) - return []; - return Object.keys(json.dependencies); + createSource(config) { + if (!config.name || !config.doComplete) { + // tslint:disable-next-line: no-console + console.error(`name and doComplete required for createSource`); + return; + } + let source = new source_1.default(Object.assign({ sourceType: types_1.SourceType.Service }, config)); + return this.addSource(source); } - 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 remove "${obj.name}" from your vim's plugin manager.`, '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 = []; - if (packageJSON.main && !fs_1.default.existsSync(filename)) { - workspace_1.default.showMessage(`extension "${id}" doesn't contain main file ${filename}.`, 'error'); - return; - } - 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.stack}`, '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); - } - } - 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); + dispose() { + util_2.disposeAll(this.disposables); } } -exports.Extensions = Extensions; -exports.default = new Extensions(); -//# sourceMappingURL=extensions.js.map +exports.Sources = Sources; +exports.default = new Sources(); +//# sourceMappingURL=sources.js.map /***/ }), -/* 254 */ +/* 255 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); -const child_process_1 = __webpack_require__(178); -const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); -const mkdirp_1 = tslib_1.__importDefault(__webpack_require__(182)); -const mv_1 = tslib_1.__importDefault(__webpack_require__(255)); +const debounce_1 = __webpack_require__(179); +const fast_diff_1 = tslib_1.__importDefault(__webpack_require__(212)); const os_1 = tslib_1.__importDefault(__webpack_require__(14)); +const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); +const isuri_1 = tslib_1.__importDefault(__webpack_require__(180)); const path_1 = tslib_1.__importDefault(__webpack_require__(20)); -const rc_1 = tslib_1.__importDefault(__webpack_require__(261)); const rimraf_1 = tslib_1.__importDefault(__webpack_require__(234)); const semver_1 = tslib_1.__importDefault(__webpack_require__(1)); -const url_1 = tslib_1.__importDefault(__webpack_require__(267)); const util_1 = __webpack_require__(12); +const vscode_languageserver_protocol_1 = __webpack_require__(150); +const vscode_uri_1 = __webpack_require__(183); +const which_1 = tslib_1.__importDefault(__webpack_require__(184)); +const commands_1 = tslib_1.__importDefault(__webpack_require__(247)); +const events_1 = tslib_1.__importDefault(__webpack_require__(149)); +const db_1 = tslib_1.__importDefault(__webpack_require__(209)); +const extension_1 = tslib_1.__importDefault(__webpack_require__(256)); +const memos_1 = tslib_1.__importDefault(__webpack_require__(313)); +const util_2 = __webpack_require__(177); +const mkdirp_1 = tslib_1.__importDefault(__webpack_require__(182)); +const array_1 = __webpack_require__(215); +__webpack_require__(314); +const factory_1 = __webpack_require__(315); +const fs_2 = __webpack_require__(203); +const watchman_1 = tslib_1.__importDefault(__webpack_require__(230)); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const download_1 = tslib_1.__importDefault(__webpack_require__(268)); -const fetch_1 = tslib_1.__importDefault(__webpack_require__(307)); -const logger = __webpack_require__(2)('model-extension'); -function registryUrl(scope = 'coc.nvim') { - const result = rc_1.default('npm', { registry: 'https://registry.npmjs.org/' }); - const registry = result[`${scope}:registry`] || result.config_registry || result.registry; - return registry.endsWith('/') ? registry : registry + '/'; -} -class ExtensionManager { - constructor(root) { - this.root = root; - this.checked = false; +const createLogger = __webpack_require__(2); +const logger = createLogger('extensions'); +function loadJson(file) { + try { + let content = fs_1.default.readFileSync(file, 'utf8'); + return JSON.parse(content); } - checkFolder() { - if (this.checked) - return; - this.checked = true; - let { root } = this; - mkdirp_1.default.sync(root); - mkdirp_1.default.sync(path_1.default.join(root, 'node_modules/.cache')); + catch (e) { + return null; } - async getInfo(ref) { - if (ref.startsWith('https:')) - return await this.getInfoFromUri(ref); - let name; - let version; - if (ref.indexOf('@') > 0) { - [name, version] = ref.split('@', 2); +} +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() { + 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'); + this.db = new db_1.default(filepath); } else { - name = ref; + await this.initializeRoot(); } - let res = await fetch_1.default(url_1.default.resolve(registryUrl(), name)); - if (!version) - version = res['dist-tags']['latest']; - let obj = res['versions'][version]; - if (!obj) - throw new Error(`${ref} not exists.`); - let requiredVersion = obj['engines'] && obj['engines']['coc']; - if (!requiredVersion) { - throw new Error(`${ref} is not valid coc extension, "engines" field with coc property required.`); + 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); + } } - return { - 'dist.tarball': obj['dist']['tarball'], - 'engines.coc': requiredVersion, - version: obj['version'], - name: res.name - }; - } - async removeFolder(folder) { - if (fs_1.default.existsSync(folder)) { - let stat = await util_1.promisify(fs_1.default.lstat)(folder); - if (stat.isSymbolicLink()) { - await util_1.promisify(fs_1.default.unlink)(folder); + 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) { + if (p) + await this.loadExtension(p, true); + } + } } - else { - await util_1.promisify(rimraf_1.default)(folder, { glob: false }); + }); + commands_1.default.register({ + id: 'extensions.forceUpdateAll', + execute: async () => { + await this.cleanExtensions(); + await this.installExtensions([]); } - } + }); } - async _install(npm, def, info, onMessage) { - let tmpFolder = await util_1.promisify(fs_1.default.mkdtemp)(path_1.default.join(os_1.default.tmpdir(), `${info.name}-`)); - let url = info['dist.tarball']; - onMessage(`Downloading from ${url}`); - await download_1.default(url, { dest: tmpFolder }); - let content = await util_1.promisify(fs_1.default.readFile)(path_1.default.join(tmpFolder, 'package.json'), 'utf8'); - let { dependencies } = JSON.parse(content); - if (dependencies && Object.keys(dependencies).length) { - onMessage(`Installing dependencies.`); - let p = new Promise((resolve, reject) => { - let args = ['install', '--ignore-scripts', '--no-lockfile', '--no-bin-links', '--production']; - if (info['dist.tarball'] && info['dist.tarball'].indexOf('github.com') !== -1) { - args = ['install']; - } - const child = child_process_1.spawn(npm, args, { cwd: tmpFolder }); - child.stderr.setEncoding('utf8'); - child.on('error', reject); - let err = ''; - child.stderr.on('data', data => { - err += data; - }); - child.on('exit', code => { - if (code) { - // tslint:disable-next-line: no-console - console.error(`${npm} install exited with ${code}, messages:\n${err}`); - } - resolve(); - }); - }); - await p; - } - let jsonFile = path_1.default.join(this.root, 'package.json'); - let obj = JSON.parse(fs_1.default.readFileSync(jsonFile, 'utf8')); - obj.dependencies = obj.dependencies || {}; - if (/^https?:/.test(def)) { - obj.dependencies[info.name] = def; + 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); } - else { - obj.dependencies[info.name] = '>=' + info.version; + // 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(); } - const sortedObj = { dependencies: {} }; - Object.keys(obj.dependencies).sort().forEach(k => { - sortedObj.dependencies[k] = obj.dependencies[k]; - }); - fs_1.default.writeFileSync(jsonFile, JSON.stringify(sortedObj, null, 2), { encoding: 'utf8' }); - onMessage(`Moving to new folder.`); - let folder = path_1.default.join(this.root, 'node_modules', info.name); - await this.removeFolder(folder); - await util_1.promisify(mv_1.default)(tmpFolder, folder, { mkdirp: true }); } - async install(npm, def) { - this.checkFolder(); - logger.info(`Using npm from: ${npm}`); - logger.info(`Loading info of ${def}.`); - let info = await this.getInfo(def); - let { name } = info; - let required = info['engines.coc'] ? info['engines.coc'].replace(/^\^/, '>=') : ''; - if (required && !semver_1.default.satisfies(workspace_1.default.version, required)) { - throw new Error(`${name} ${info.version} requires coc.nvim >= ${required}, please update coc.nvim.`); - } - await this._install(npm, def, info, msg => { - logger.info(msg); - }); - workspace_1.default.showMessage(`Installed extension: ${name}`, 'more'); - logger.info(`Installed extension: ${name}`); - return name; + async updateExtensions() { + if (!this.root) + await this.initializeRoot(); + if (!this.npm) + return; + let lockedList = await this.getLockedList(); + let stats = await this.globalExtensionStats(); + 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(); + this.db.push('lastUpdate', Date.now()); + await util_2.concurrent(names.map(name => { + let o = stats.find(o => o.id == name); + return () => { + 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}`); + }); + }; + }), 5); + workspace_1.default.showMessage('Update completed', 'more'); + statusItem.dispose(); } - async update(npm, name, uri) { - this.checkFolder(); - let folder = path_1.default.join(this.root, 'node_modules', name); - let stat = await util_1.promisify(fs_1.default.lstat)(folder); - if (stat.isSymbolicLink()) { - logger.info(`skipped update of ${name}`); - return false; - } - let version; - if (fs_1.default.existsSync(path_1.default.join(folder, 'package.json'))) { - let content = await util_1.promisify(fs_1.default.readFile)(path_1.default.join(folder, 'package.json'), 'utf8'); - version = JSON.parse(content).version; - } - logger.info(`Loading info of ${name}.`); - let info = await this.getInfo(uri ? uri : name); - if (version && info.version && semver_1.default.gte(version, info.version)) { - logger.info(`Extension ${name} is up to date.`); - return false; + 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.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(); } - let required = info['engines.coc'] ? info['engines.coc'].replace(/^\^/, '>=') : ''; - if (required && !semver_1.default.satisfies(workspace_1.default.version, required)) { - throw new Error(`${name} ${info.version} requires coc.nvim >= ${required}, please update coc.nvim.`); + // 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.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 + }); + } + } } - await this._install(npm, uri ? uri : name, info, msg => { logger.info(msg); }); - workspace_1.default.showMessage(`Updated extension: ${name} to ${info.version}`, 'more'); - logger.info(`Update extension: ${name}`); - return true; - } - async getInfoFromUri(uri) { - if (uri.indexOf('github.com') == -1) - return; - uri = uri.replace(/\/$/, ''); - let fileUrl = uri.replace('github.com', 'raw.githubusercontent.com') + '/master/package.json'; - let content = await fetch_1.default(fileUrl); - let obj = typeof content == 'string' ? JSON.parse(content) : content; - return { - 'dist.tarball': `${uri}/archive/master.tar.gz`, - 'engines.coc': obj['engines'] ? obj['engines']['coc'] : undefined, - name: obj.name, - version: obj.version - }; } -} -exports.default = ExtensionManager; -//# sourceMappingURL=extension.js.map - -/***/ }), -/* 255 */ -/***/ (function(module, exports, __webpack_require__) { - -var fs = __webpack_require__(4); -var ncp = __webpack_require__(256).ncp; -var path = __webpack_require__(20); -var rimraf = __webpack_require__(257); -var mkdirp = __webpack_require__(182); - -module.exports = mv; - -function mv(source, dest, options, cb){ - if (typeof options === 'function') { - cb = options; - options = {}; - } - var shouldMkdirp = !!options.mkdirp; - var clobber = options.clobber !== false; - var limit = options.limit || 16; - - if (shouldMkdirp) { - mkdirs(); - } else { - doRename(); - } - - function mkdirs() { - mkdirp(path.dirname(dest), function(err) { - if (err) return cb(err); - doRename(); - }); - } - - function doRename() { - if (clobber) { - fs.rename(source, dest, function(err) { - if (!err) return cb(); - if (err.code !== 'EXDEV') return cb(err); - moveFileAcrossDevice(source, dest, clobber, limit, cb); - }); - } else { - fs.link(source, dest, function(err) { - if (err) { - if (err.code === 'EXDEV') { - moveFileAcrossDevice(source, dest, clobber, limit, cb); + /** + * Install extensions, can be called without initialize. + */ + async installExtensions(list = []) { + let { npm } = this; + if (!npm) return; - } - if (err.code === 'EISDIR' || err.code === 'EPERM') { - moveDirAcrossDevice(source, dest, clobber, limit, cb); + if (!this.root) + await this.initializeRoot(); + let missing = this.getMissingExtensions(); + if (missing.length) + list.push(...missing); + if (!list.length) return; - } - cb(err); - return; - } - fs.unlink(source, cb); - }); + 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(); } - } -} - -function moveFileAcrossDevice(source, dest, clobber, limit, cb) { - var outFlags = clobber ? 'w' : 'wx'; - var ins = fs.createReadStream(source); - var outs = fs.createWriteStream(dest, {flags: outFlags}); - ins.on('error', function(err){ - ins.destroy(); - outs.destroy(); - outs.removeListener('close', onClose); - if (err.code === 'EISDIR' || err.code === 'EPERM') { - moveDirAcrossDevice(source, dest, clobber, limit, cb); - } else { - cb(err); + /** + * 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; } - }); - outs.on('error', function(err){ - ins.destroy(); - outs.destroy(); - outs.removeListener('close', onClose); - cb(err); - }); - outs.once('close', onClose); - ins.pipe(outs); - function onClose(){ - fs.unlink(source, cb); - } -} - -function moveDirAcrossDevice(source, dest, clobber, limit, cb) { - var options = { - stopOnErr: true, - clobber: false, - limit: limit, - }; - if (clobber) { - rimraf(dest, { disableGlob: true }, function(err) { - if (err) return cb(err); - startNcp(); - }); - } else { - startNcp(); - } - function startNcp() { - ncp(source, dest, options, function(errList) { - if (errList) return cb(errList[0]); - rimraf(source, { disableGlob: true }, cb); - }); - } -} - - -/***/ }), -/* 256 */ -/***/ (function(module, exports, __webpack_require__) { - -var fs = __webpack_require__(4), - path = __webpack_require__(20); - -module.exports = ncp; -ncp.ncp = ncp; - -function ncp (source, dest, options, callback) { - var cback = callback; - - if (!callback) { - cback = options; - options = {}; - } - - var basePath = process.cwd(), - currentPath = path.resolve(basePath, source), - targetPath = path.resolve(basePath, dest), - filter = options.filter, - rename = options.rename, - transform = options.transform, - clobber = options.clobber !== false, - modified = options.modified, - dereference = options.dereference, - errs = null, - started = 0, - finished = 0, - running = 0, - limit = options.limit || ncp.limit || 16; - - limit = (limit < 1) ? 1 : (limit > 512) ? 512 : limit; - - startCopy(currentPath); - - function startCopy(source) { - started++; - if (filter) { - if (filter instanceof RegExp) { - if (!filter.test(source)) { - return cb(true); + get npm() { + let npm = workspace_1.default.getConfiguration('npm').get('binPath', 'npm'); + if (npm.startsWith('~')) { + npm = os_1.default.homedir() + npm.slice(1); } - } - else if (typeof filter === 'function') { - if (!filter(source)) { - return cb(true); + 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; } - return getStats(source); - } - - function getStats(source) { - var stat = dereference ? fs.stat : fs.lstat; - if (running >= limit) { - return setImmediate(function () { - getStats(source); - }); + /** + * Get all loaded extensions. + */ + get all() { + return this.list.map(o => o.extension); } - running++; - stat(source, function (err, stats) { - var item = {}; - if (err) { - return onError(err); - } - - // We need to get the mode from the stats object and preserve it. - item.name = source; - item.mode = stats.mode; - item.mtime = stats.mtime; //modified time - item.atime = stats.atime; //access time - - if (stats.isDirectory()) { - return onDir(item); - } - else if (stats.isFile()) { - return onFile(item); - } - else if (stats.isSymbolicLink()) { - // Symlinks don't really need to know about the mode. - return onLink(source); - } - }); - } - - function onFile(file) { - var target = file.name.replace(currentPath, targetPath); - if(rename) { - target = rename(target); + getExtension(id) { + return this.list.find(o => o.id == id); } - isWritable(target, function (writable) { - if (writable) { - return copyFile(file, target); - } - if(clobber) { - rmFile(target, function () { - copyFile(file, target); - }); - } - if (modified) { - var stat = dereference ? fs.stat : fs.lstat; - stat(target, function(err, stats) { - //if souce modified time greater to target modified time copy file - if (file.mtime.getTime()>stats.mtime.getTime()) - copyFile(file, target); - else return cb(); + 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; }); - } - else { - return cb(); - } - }); - } - - function copyFile(file, target) { - var readStream = fs.createReadStream(file.name), - writeStream = fs.createWriteStream(target, { mode: file.mode }); - - readStream.on('error', onError); - writeStream.on('error', onError); - - if(transform) { - transform(readStream, writeStream, file); - } else { - writeStream.on('open', function() { - readStream.pipe(writeStream); - }); } - writeStream.once('finish', function() { - if (modified) { - //target file modified date sync. - fs.utimesSync(target, file.atime, file.mtime); - cb(); + async toggleLock(id) { + let key = `extension.${id}.locked`; + let locked = await this.db.fetch(key); + if (locked) { + this.db.delete(key); } - else cb(); - }); - } - - function rmFile(file, done) { - fs.unlink(file, function (err) { - if (err) { - return onError(err); - } - return done(); - }); - } - - function onDir(dir) { - var target = dir.name.replace(currentPath, targetPath); - isWritable(target, function (writable) { - if (writable) { - return mkDir(dir, target); - } - copyDir(dir.name); - }); - } - - function mkDir(dir, target) { - fs.mkdir(target, dir.mode, function (err) { - if (err) { - return onError(err); - } - copyDir(dir.name); - }); - } - - function copyDir(dir) { - fs.readdir(dir, function (err, items) { - if (err) { - return onError(err); - } - items.forEach(function (item) { - startCopy(path.join(dir, item)); - }); - return cb(); - }); - } - - function onLink(link) { - var target = link.replace(currentPath, targetPath); - fs.readlink(link, function (err, resolvedPath) { - if (err) { - return onError(err); - } - checkLink(resolvedPath, target); - }); - } - - function checkLink(resolvedPath, target) { - if (dereference) { - resolvedPath = path.resolve(basePath, resolvedPath); - } - isWritable(target, function (writable) { - if (writable) { - return makeLink(resolvedPath, target); - } - fs.readlink(target, function (err, targetDest) { - if (err) { - return onError(err); + else { + this.db.push(key, true); } - if (dereference) { - targetDest = path.resolve(basePath, targetDest); + } + async toggleExtension(id) { + let state = this.getExtensionState(id); + if (state == null) + return; + if (state == 'activated') { + this.deactivate(id); } - if (targetDest === resolvedPath) { - return cb(); + 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); } - return rmFile(target, function () { - makeLink(resolvedPath, target); - }); - }); - }); - } - - function makeLink(linkPath, target) { - fs.symlink(linkPath, target, function (err) { - if (err) { - return onError(err); - } - return cb(); - }); - } - - function isWritable(path, done) { - fs.lstat(path, function (err) { - if (err) { - if (err.code === 'ENOENT') return done(true); - return done(false); - } - return done(false); - }); - } - - function onError(err) { - if (options.stopOnError) { - return cback(err); - } - else if (!errs && options.errs) { - errs = fs.createWriteStream(options.errs); + 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); } - else if (!errs) { - errs = []; + 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); + } } - if (typeof errs.write === 'undefined') { - errs.push(err); + /** + * 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 }); + } } - else { - errs.write(err.stack + '\n\n'); + 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.promisify(rimraf_1.default)(`${folder}`, { glob: false }); + } + } + let jsonFile = path_1.default.join(this.root, 'package.json'); + status.dispose(); + const sortedObj = { dependencies: {} }; + Object.keys(json.dependencies).sort().forEach(k => { + sortedObj.dependencies[k] = json.dependencies[k]; + }); + fs_1.default.writeFileSync(jsonFile, JSON.stringify(sortedObj, null, 2), { encoding: 'utf8' }); + workspace_1.default.showMessage(`Removed: ${ids.join(' ')}`); + } + catch (e) { + status.dispose(); + workspace_1.default.showMessage(`Uninstall failed: ${e.message}`, 'error'); + } } - return cb(); - } - - function cb(skipped) { - if (!skipped) running--; - finished++; - if ((started === finished) && (running === 0)) { - if (cback !== undefined ) { - return errs ? cback(errs) : cback(null); - } + isDisabled(id) { + return this.disabled.has(id); } - } -} - - - - -/***/ }), -/* 257 */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = rimraf -rimraf.sync = rimrafSync - -var assert = __webpack_require__(46) -var path = __webpack_require__(20) -var fs = __webpack_require__(4) -var glob = __webpack_require__(258) - -var globOpts = { - nosort: true, - nocomment: true, - nonegate: true, - silent: true -} - -// for EMFILE handling -var timeout = 0 - -var isWindows = (process.platform === "win32") - -function defaults (options) { - var methods = [ - 'unlink', - 'chmod', - 'stat', - 'lstat', - 'rmdir', - 'readdir' - ] - methods.forEach(function(m) { - options[m] = options[m] || fs[m] - m = m + 'Sync' - options[m] = options[m] || fs[m] - }) - - options.maxBusyTries = options.maxBusyTries || 3 - options.emfileWait = options.emfileWait || 1000 - options.disableGlob = options.disableGlob || false -} - -function rimraf (p, options, cb) { - if (typeof options === 'function') { - cb = options - options = {} - } - - assert(p, 'rimraf: missing path') - assert.equal(typeof p, 'string', 'rimraf: path should be a string') - assert(options, 'rimraf: missing options') - assert.equal(typeof options, 'object', 'rimraf: options should be object') - assert.equal(typeof cb, 'function', 'rimraf: callback function required') - - defaults(options) - - var busyTries = 0 - var errState = null - var n = 0 - - if (options.disableGlob || !glob.hasMagic(p)) - return afterGlob(null, [p]) - - fs.lstat(p, function (er, stat) { - if (!er) - return afterGlob(null, [p]) - - glob(p, globOpts, afterGlob) - }) - - function next (er) { - errState = errState || er - if (--n === 0) - cb(errState) - } - - function afterGlob (er, results) { - if (er) - return cb(er) - - n = results.length - if (n === 0) - return cb() - - results.forEach(function (p) { - rimraf_(p, options, function CB (er) { - if (er) { - if (isWindows && (er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") && - busyTries < options.maxBusyTries) { - busyTries ++ - var time = busyTries * 100 - // try again, with the same exact callback as this one. - return setTimeout(function () { - rimraf_(p, options, CB) - }, time) - } - - // this one won't happen if graceful-fs is used. - if (er.code === "EMFILE" && timeout < options.emfileWait) { - return setTimeout(function () { - rimraf_(p, options, CB) - }, timeout ++) - } - - // already gone - if (er.code === "ENOENT") er = null + 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); } - - timeout = 0 - next(er) - }) - }) - } -} - -// Two possible strategies. -// 1. Assume it's a file. unlink it, then do the dir stuff on EPERM or EISDIR -// 2. Assume it's a directory. readdir, then do the file stuff on ENOTDIR -// -// Both result in an extra syscall when you guess wrong. However, there -// are likely far more normal files in the world than directories. This -// is based on the assumption that a the average number of files per -// directory is >= 1. -// -// If anyone ever complains about this, then I guess the strategy could -// be made configurable somehow. But until then, YAGNI. -function rimraf_ (p, options, cb) { - assert(p) - assert(options) - assert(typeof cb === 'function') - - // sunos lets the root user unlink directories, which is... weird. - // so we have to lstat here and make sure it's not a dir. - options.lstat(p, function (er, st) { - if (er && er.code === "ENOENT") - return cb(null) - - if (st && st.isDirectory()) - return rmdir(p, options, er, cb) - - options.unlink(p, function (er) { - if (er) { - if (er.code === "ENOENT") - return cb(null) - if (er.code === "EPERM") - return (isWindows) - ? fixWinEPERM(p, options, er, cb) - : rmdir(p, options, er, cb) - if (er.code === "EISDIR") - return rmdir(p, options, er, cb) - } - return cb(er) - }) - }) -} - -function fixWinEPERM (p, options, er, cb) { - assert(p) - assert(options) - assert(typeof cb === 'function') - if (er) - assert(er instanceof Error) - - options.chmod(p, 666, function (er2) { - if (er2) - cb(er2.code === "ENOENT" ? null : er) - else - options.stat(p, function(er3, stats) { - if (er3) - cb(er3.code === "ENOENT" ? null : er) - else if (stats.isDirectory()) - rmdir(p, options, er, cb) - else - options.unlink(p, cb) - }) - }) -} - -function fixWinEPERMSync (p, options, er) { - assert(p) - assert(options) - if (er) - assert(er instanceof Error) - - try { - options.chmodSync(p, 666) - } catch (er2) { - if (er2.code === "ENOENT") - return - else - throw er - } - - try { - var stats = options.statSync(p) - } catch (er3) { - if (er3.code === "ENOENT") - return - else - throw er - } - - if (stats.isDirectory()) - rmdirSync(p, options, er) - else - options.unlinkSync(p) -} - -function rmdir (p, options, originalEr, cb) { - assert(p) - assert(options) - if (originalEr) - assert(originalEr instanceof Error) - assert(typeof cb === 'function') - - // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS) - // if we guessed wrong, and it's not a directory, then - // raise the original error. - options.rmdir(p, function (er) { - if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM")) - rmkids(p, options, cb) - else if (er && er.code === "ENOTDIR") - cb(originalEr) - else - cb(er) - }) -} - -function rmkids(p, options, cb) { - assert(p) - assert(options) - assert(typeof cb === 'function') - - options.readdir(p, function (er, files) { - if (er) - return cb(er) - var n = files.length - if (n === 0) - return options.rmdir(p, cb) - var errState - files.forEach(function (f) { - rimraf(path.join(p, f), options, function (er) { - if (errState) - return - if (er) - return cb(errState = er) - if (--n === 0) - options.rmdir(p, cb) - }) - }) - }) -} - -// this looks simpler, and is strictly *faster*, but will -// tie up the JavaScript thread and fail on excessively -// deep directory trees. -function rimrafSync (p, options) { - options = options || {} - defaults(options) - - assert(p, 'rimraf: missing path') - assert.equal(typeof p, 'string', 'rimraf: path should be a string') - assert(options, 'rimraf: missing options') - assert.equal(typeof options, 'object', 'rimraf: options should be object') - - var results - - if (options.disableGlob || !glob.hasMagic(p)) { - results = [p] - } else { - try { - fs.lstatSync(p) - results = [p] - } catch (er) { - results = glob.sync(p, globOpts) } - } - - if (!results.length) - return - - for (var i = 0; i < results.length; i++) { - var p = results[i] - - try { - var st = options.lstatSync(p) - } catch (er) { - if (er.code === "ENOENT") - return + has(id) { + return this.list.find(o => o.id == id) != null; } - - try { - // sunos lets the root user unlink directories, which is... weird. - if (st && st.isDirectory()) - rmdirSync(p, options, null) - else - options.unlinkSync(p) - } catch (er) { - if (er.code === "ENOENT") - return - if (er.code === "EPERM") - return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er) - if (er.code !== "EISDIR") - throw er - rmdirSync(p, options, er) + isActivated(id) { + let item = this.list.find(o => o.id == id); + if (item && item.extension.isActive) { + return true; + } + return false; } - } -} - -function rmdirSync (p, options, originalEr) { - assert(p) - assert(options) - if (originalEr) - assert(originalEr instanceof Error) - - try { - options.rmdirSync(p) - } catch (er) { - if (er.code === "ENOENT") - return - if (er.code === "ENOTDIR") - throw originalEr - if (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM") - rmkidsSync(p, options) - } -} - -function rmkidsSync (p, options) { - assert(p) - assert(options) - options.readdirSync(p).forEach(function (f) { - rimrafSync(path.join(p, f), options) - }) - options.rmdirSync(p, options) -} - - -/***/ }), -/* 258 */ -/***/ (function(module, exports, __webpack_require__) { - -// Approach: -// -// 1. Get the minimatch set -// 2. For each pattern in the set, PROCESS(pattern, false) -// 3. Store matches per-set, then uniq them -// -// PROCESS(pattern, inGlobStar) -// Get the first [n] items from pattern that are all strings -// Join these together. This is PREFIX. -// If there is no more remaining, then stat(PREFIX) and -// add to matches if it succeeds. END. -// -// If inGlobStar and PREFIX is symlink and points to dir -// set ENTRIES = [] -// else readdir(PREFIX) as ENTRIES -// If fail, END -// -// with ENTRIES -// If pattern[n] is GLOBSTAR -// // handle the case where the globstar match is empty -// // by pruning it out, and testing the resulting pattern -// PROCESS(pattern[0..n] + pattern[n+1 .. $], false) -// // handle other cases. -// for ENTRY in ENTRIES (not dotfiles) -// // attach globstar + tail onto the entry -// // Mark that this entry is a globstar match -// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true) -// -// else // not globstar -// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot) -// Test ENTRY against pattern[n] -// If fails, continue -// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $]) -// -// Caveat: -// Cache all stats and readdirs results to minimize syscall. Since all -// we ever care about is existence and directory-ness, we can just keep -// `true` for files, and [children,...] for directories, or `false` for -// things that don't exist. - -module.exports = glob - -var fs = __webpack_require__(4) -var minimatch = __webpack_require__(204) -var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(238) -var EE = __webpack_require__(137).EventEmitter -var path = __webpack_require__(20) -var assert = __webpack_require__(46) -var isAbsolute = __webpack_require__(240) -var globSync = __webpack_require__(259) -var common = __webpack_require__(260) -var alphasort = common.alphasort -var alphasorti = common.alphasorti -var setopts = common.setopts -var ownProp = common.ownProp -var inflight = __webpack_require__(243) -var util = __webpack_require__(12) -var childrenIgnored = common.childrenIgnored -var isIgnored = common.isIgnored - -var once = __webpack_require__(245) - -function glob (pattern, options, cb) { - if (typeof options === 'function') cb = options, options = {} - if (!options) options = {} - - if (options.sync) { - if (cb) - throw new TypeError('callback provided to sync glob') - return globSync(pattern, options) - } - - return new Glob(pattern, options, cb) -} - -glob.sync = globSync -var GlobSync = glob.GlobSync = globSync.GlobSync - -// old api surface -glob.glob = glob - -function extend (origin, add) { - if (add === null || typeof add !== 'object') { - return origin - } - - var keys = Object.keys(add) - var i = keys.length - while (i--) { - origin[keys[i]] = add[keys[i]] - } - return origin -} - -glob.hasMagic = function (pattern, options_) { - var options = extend({}, options_) - options.noprocess = true - - var g = new Glob(pattern, options) - var set = g.minimatch.set - if (set.length > 1) - return true - - for (var j = 0; j < set[0].length; j++) { - if (typeof set[0][j] !== 'string') - return true - } - - return false -} - -glob.Glob = Glob -inherits(Glob, EE) -function Glob (pattern, options, cb) { - if (typeof options === 'function') { - cb = options - options = null - } - - if (options && options.sync) { - if (cb) - throw new TypeError('callback provided to sync glob') - return new GlobSync(pattern, options) - } - - if (!(this instanceof Glob)) - return new Glob(pattern, options, cb) - - setopts(this, pattern, options) - this._didRealPath = false - - // process each pattern in the minimatch set - var n = this.minimatch.set.length - - // The matches are stored as {: true,...} so that - // duplicates are automagically pruned. - // Later, we do an Object.keys() on these. - // Keep them as a list so we can fill in when nonull is set. - this.matches = new Array(n) - - if (typeof cb === 'function') { - cb = once(cb) - this.on('error', cb) - this.on('end', function (matches) { - cb(null, matches) - }) - } - - var self = this - var n = this.minimatch.set.length - this._processing = 0 - this.matches = new Array(n) - - this._emitQueue = [] - this._processQueue = [] - this.paused = false - - if (this.noprocess) - return this - - if (n === 0) - return done() - - for (var i = 0; i < n; i ++) { - this._process(this.minimatch.set[i], i, false, done) - } - - function done () { - --self._processing - if (self._processing <= 0) - self._finish() - } -} - -Glob.prototype._finish = function () { - assert(this instanceof Glob) - if (this.aborted) - return - - if (this.realpath && !this._didRealpath) - return this._realpath() - - common.finish(this) - this.emit('end', this.found) -} - -Glob.prototype._realpath = function () { - if (this._didRealpath) - return - - this._didRealpath = true - - var n = this.matches.length - if (n === 0) - return this._finish() - - var self = this - for (var i = 0; i < this.matches.length; i++) - this._realpathSet(i, next) - - function next () { - if (--n === 0) - self._finish() - } -} - -Glob.prototype._realpathSet = function (index, cb) { - var matchset = this.matches[index] - if (!matchset) - return cb() - - var found = Object.keys(matchset) - var self = this - var n = found.length - - if (n === 0) - return cb() - - var set = this.matches[index] = Object.create(null) - found.forEach(function (p, i) { - // If there's a problem with the stat, then it means that - // one or more of the links in the realpath couldn't be - // resolved. just return the abs value in that case. - p = self._makeAbs(p) - fs.realpath(p, self.realpathCache, function (er, real) { - if (!er) - set[real] = true - else if (er.syscall === 'stat') - set[p] = true - else - self.emit('error', er) // srsly wtf right here - - if (--n === 0) { - self.matches[index] = set - cb() - } - }) - }) -} - -Glob.prototype._mark = function (p) { - return common.mark(this, p) -} - -Glob.prototype._makeAbs = function (f) { - return common.makeAbs(this, f) -} - -Glob.prototype.abort = function () { - this.aborted = true - this.emit('abort') -} - -Glob.prototype.pause = function () { - if (!this.paused) { - this.paused = true - this.emit('pause') - } -} - -Glob.prototype.resume = function () { - if (this.paused) { - this.emit('resume') - this.paused = false - if (this._emitQueue.length) { - var eq = this._emitQueue.slice(0) - this._emitQueue.length = 0 - for (var i = 0; i < eq.length; i ++) { - var e = eq[i] - this._emitMatch(e[0], e[1]) - } + 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.isActivated(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}`); + } } - if (this._processQueue.length) { - var pq = this._processQueue.slice(0) - this._processQueue.length = 0 - for (var i = 0; i < pq.length; i ++) { - var p = pq[i] - this._processing-- - this._process(p[0], p[1], p[2], p[3]) - } + async loadFileExtensions() { + if (!process.env.COC_VIMCONFIG) + return; + let folder = path_1.default.join(process.env.COC_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)); + } } - } -} - -Glob.prototype._process = function (pattern, index, inGlobStar, cb) { - assert(this instanceof Glob) - assert(typeof cb === 'function') - - if (this.aborted) - return - - this._processing++ - if (this.paused) { - this._processQueue.push([pattern, index, inGlobStar, cb]) - return - } - - //console.error('PROCESS %d', this._processing, pattern) - - // Get the first [n] parts of pattern that are all strings. - var n = 0 - while (typeof pattern[n] === 'string') { - n ++ - } - // now n is the index of the first one that is *not* a string. - - // see if there's anything else - var prefix - switch (n) { - // if not, then this is rather simple - case pattern.length: - this._processSimple(pattern.join('/'), index, cb) - return - - case 0: - // pattern *starts* with some non-trivial item. - // going to readdir(cwd), but not include the prefix in matches. - prefix = null - break - - default: - // pattern has some string bits in the front. - // whatever it starts with, whether that's 'absolute' like /foo/bar, - // or 'relative' like '../baz' - prefix = pattern.slice(0, n).join('/') - break - } - - var remain = pattern.slice(n) - - // get the list of entries. - var read - if (prefix === null) - read = '.' - else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { - if (!prefix || !isAbsolute(prefix)) - prefix = '/' + prefix - read = prefix - } else - read = prefix - - var abs = this._makeAbs(read) - - //if ignored, skip _processing - if (childrenIgnored(this, read)) - return cb() - - var isGlobStar = remain[0] === minimatch.GLOBSTAR - if (isGlobStar) - this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb) - else - this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb) -} - -Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) { - var self = this - this._readdir(abs, inGlobStar, function (er, entries) { - return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb) - }) -} - -Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { - - // if the abs isn't a dir, then nothing can match! - if (!entries) - return cb() - - // It will only match dot entries if it starts with a dot, or if - // dot is set. Stuff like @(.foo|.bar) isn't allowed. - var pn = remain[0] - var negate = !!this.minimatch.negate - var rawGlob = pn._glob - var dotOk = this.dot || rawGlob.charAt(0) === '.' - - var matchedEntries = [] - for (var i = 0; i < entries.length; i++) { - var e = entries[i] - if (e.charAt(0) !== '.' || dotOk) { - var m - if (negate && !prefix) { - m = !e.match(pn) - } else { - m = e.match(pn) - } - if (m) - matchedEntries.push(e) + /** + * 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); } - } - - //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries) - - var len = matchedEntries.length - // If there are no matched entries, then nothing matches. - if (len === 0) - return cb() - - // if this is the last remaining pattern bit, then no need for - // an additional stat *unless* the user has specified mark or - // stat explicitly. We know they exist, since readdir returned - // them. - - if (remain.length === 1 && !this.mark && !this.stat) { - if (!this.matches[index]) - this.matches[index] = Object.create(null) - - for (var i = 0; i < len; i ++) { - var e = matchedEntries[i] - if (prefix) { - if (prefix !== '/') - e = prefix + '/' + e - else - e = prefix + e - } - - if (e.charAt(0) === '/' && !this.nomount) { - e = path.join(this.root, e) - } - this._emitMatch(index, e) + 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.stack}`, 'error'); + logger.error(`Error on activate extension ${extension.id}:`, e); + }); } - // This was the last one, and no stats were needed - return cb() - } - - // now test all matched entries as stand-ins for that part - // of the pattern. - remain.shift() - for (var i = 0; i < len; i ++) { - var e = matchedEntries[i] - var newPattern - if (prefix) { - if (prefix !== '/') - e = prefix + '/' + e - else - e = prefix + 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 remove "${obj.name}" from your vim's plugin manager.`, '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 = []; + if (packageJSON.main && !fs_1.default.existsSync(filename)) { + workspace_1.default.showMessage(`extension "${id}" doesn't contain main file ${filename}.`, 'error'); + return; + } + 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.stack}`, '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); + } + } + 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); } - this._process([e].concat(remain), index, inGlobStar, cb) - } - cb() -} - -Glob.prototype._emitMatch = function (index, e) { - if (this.aborted) - return - - if (this.matches[index][e]) - return - - if (isIgnored(this, e)) - return - - if (this.paused) { - this._emitQueue.push([index, e]) - return - } - - var abs = this._makeAbs(e) - - if (this.nodir) { - var c = this.cache[abs] - if (c === 'DIR' || Array.isArray(c)) - return - } - - if (this.mark) - e = this._mark(e) - - this.matches[index][e] = true - - var st = this.statCache[abs] - if (st) - this.emit('stat', e, st) - - this.emit('match', e) -} - -Glob.prototype._readdirInGlobStar = function (abs, cb) { - if (this.aborted) - return - - // follow all symlinked directories forever - // just proceed as if this is a non-globstar situation - if (this.follow) - return this._readdir(abs, false, cb) - - var lstatkey = 'lstat\0' + abs - var self = this - var lstatcb = inflight(lstatkey, lstatcb_) - - if (lstatcb) - fs.lstat(abs, lstatcb) - - function lstatcb_ (er, lstat) { - if (er) - return cb() - - var isSym = lstat.isSymbolicLink() - self.symlinks[abs] = isSym - - // If it's not a symlink or a dir, then it's definitely a regular file. - // don't bother doing a readdir in that case. - if (!isSym && !lstat.isDirectory()) { - self.cache[abs] = 'FILE' - cb() - } else - self._readdir(abs, false, cb) - } } +exports.Extensions = Extensions; +exports.default = new Extensions(); +//# sourceMappingURL=extensions.js.map -Glob.prototype._readdir = function (abs, inGlobStar, cb) { - if (this.aborted) - return - - cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb) - if (!cb) - return - - //console.error('RD %j %j', +inGlobStar, abs) - if (inGlobStar && !ownProp(this.symlinks, abs)) - return this._readdirInGlobStar(abs, cb) - - if (ownProp(this.cache, abs)) { - var c = this.cache[abs] - if (!c || c === 'FILE') - return cb() - - if (Array.isArray(c)) - return cb(null, c) - } +/***/ }), +/* 256 */ +/***/ (function(module, exports, __webpack_require__) { - var self = this - fs.readdir(abs, readdirCb(this, abs, cb)) -} +"use strict"; -function readdirCb (self, abs, cb) { - return function (er, entries) { - if (er) - self._readdirError(abs, er, cb) - else - self._readdirEntries(abs, entries, cb) - } +Object.defineProperty(exports, "__esModule", { value: true }); +const tslib_1 = __webpack_require__(3); +const child_process_1 = __webpack_require__(178); +const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); +const mkdirp_1 = tslib_1.__importDefault(__webpack_require__(182)); +const mv_1 = tslib_1.__importDefault(__webpack_require__(257)); +const os_1 = tslib_1.__importDefault(__webpack_require__(14)); +const path_1 = tslib_1.__importDefault(__webpack_require__(20)); +const rc_1 = tslib_1.__importDefault(__webpack_require__(263)); +const rimraf_1 = tslib_1.__importDefault(__webpack_require__(234)); +const semver_1 = tslib_1.__importDefault(__webpack_require__(1)); +const url_1 = tslib_1.__importDefault(__webpack_require__(269)); +const util_1 = __webpack_require__(12); +const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); +const download_1 = tslib_1.__importDefault(__webpack_require__(270)); +const fetch_1 = tslib_1.__importDefault(__webpack_require__(309)); +const logger = __webpack_require__(2)('model-extension'); +function registryUrl(scope = 'coc.nvim') { + const result = rc_1.default('npm', { registry: 'https://registry.npmjs.org/' }); + const registry = result[`${scope}:registry`] || result.config_registry || result.registry; + return registry.endsWith('/') ? registry : registry + '/'; } - -Glob.prototype._readdirEntries = function (abs, entries, cb) { - if (this.aborted) - return - - // if we haven't asked to stat everything, then just - // assume that everything in there exists, so we can avoid - // having to stat it a second time. - if (!this.mark && !this.stat) { - for (var i = 0; i < entries.length; i ++) { - var e = entries[i] - if (abs === '/') - e = abs + e - else - e = abs + '/' + e - this.cache[e] = true +class ExtensionManager { + constructor(root) { + this.root = root; + this.checked = false; + } + checkFolder() { + if (this.checked) + return; + this.checked = true; + let { root } = this; + mkdirp_1.default.sync(root); + mkdirp_1.default.sync(path_1.default.join(root, 'node_modules/.cache')); + } + async getInfo(ref) { + if (ref.startsWith('https:')) + return await this.getInfoFromUri(ref); + let name; + let version; + if (ref.indexOf('@') > 0) { + [name, version] = ref.split('@', 2); + } + else { + name = ref; + } + let res = await fetch_1.default(url_1.default.resolve(registryUrl(), name)); + if (!version) + version = res['dist-tags']['latest']; + let obj = res['versions'][version]; + if (!obj) + throw new Error(`${ref} not exists.`); + let requiredVersion = obj['engines'] && obj['engines']['coc']; + if (!requiredVersion) { + throw new Error(`${ref} is not valid coc extension, "engines" field with coc property required.`); + } + return { + 'dist.tarball': obj['dist']['tarball'], + 'engines.coc': requiredVersion, + version: obj['version'], + name: res.name + }; + } + async removeFolder(folder) { + if (fs_1.default.existsSync(folder)) { + let stat = await util_1.promisify(fs_1.default.lstat)(folder); + if (stat.isSymbolicLink()) { + await util_1.promisify(fs_1.default.unlink)(folder); + } + else { + await util_1.promisify(rimraf_1.default)(folder, { glob: false }); + } + } + } + async _install(npm, def, info, onMessage) { + let tmpFolder = await util_1.promisify(fs_1.default.mkdtemp)(path_1.default.join(os_1.default.tmpdir(), `${info.name}-`)); + let url = info['dist.tarball']; + onMessage(`Downloading from ${url}`); + await download_1.default(url, { dest: tmpFolder }); + let content = await util_1.promisify(fs_1.default.readFile)(path_1.default.join(tmpFolder, 'package.json'), 'utf8'); + let { dependencies } = JSON.parse(content); + if (dependencies && Object.keys(dependencies).length) { + onMessage(`Installing dependencies.`); + let p = new Promise((resolve, reject) => { + let args = ['install', '--ignore-scripts', '--no-lockfile', '--no-bin-links', '--production']; + if (info['dist.tarball'] && info['dist.tarball'].indexOf('github.com') !== -1) { + args = ['install']; + } + const child = child_process_1.spawn(npm, args, { cwd: tmpFolder }); + child.stderr.setEncoding('utf8'); + child.on('error', reject); + let err = ''; + child.stderr.on('data', data => { + err += data; + }); + child.on('exit', code => { + if (code) { + // tslint:disable-next-line: no-console + console.error(`${npm} install exited with ${code}, messages:\n${err}`); + } + resolve(); + }); + }); + await p; + } + let jsonFile = path_1.default.join(this.root, 'package.json'); + let obj = JSON.parse(fs_1.default.readFileSync(jsonFile, 'utf8')); + obj.dependencies = obj.dependencies || {}; + if (/^https?:/.test(def)) { + obj.dependencies[info.name] = def; + } + else { + obj.dependencies[info.name] = '>=' + info.version; + } + const sortedObj = { dependencies: {} }; + Object.keys(obj.dependencies).sort().forEach(k => { + sortedObj.dependencies[k] = obj.dependencies[k]; + }); + fs_1.default.writeFileSync(jsonFile, JSON.stringify(sortedObj, null, 2), { encoding: 'utf8' }); + onMessage(`Moving to new folder.`); + let folder = path_1.default.join(this.root, 'node_modules', info.name); + await this.removeFolder(folder); + await util_1.promisify(mv_1.default)(tmpFolder, folder, { mkdirp: true }); + } + async install(npm, def) { + this.checkFolder(); + logger.info(`Using npm from: ${npm}`); + logger.info(`Loading info of ${def}.`); + let info = await this.getInfo(def); + let { name } = info; + let required = info['engines.coc'] ? info['engines.coc'].replace(/^\^/, '>=') : ''; + if (required && !semver_1.default.satisfies(workspace_1.default.version, required)) { + throw new Error(`${name} ${info.version} requires coc.nvim >= ${required}, please update coc.nvim.`); + } + await this._install(npm, def, info, msg => { + logger.info(msg); + }); + workspace_1.default.showMessage(`Installed extension: ${name}`, 'more'); + logger.info(`Installed extension: ${name}`); + return name; + } + async update(npm, name, uri) { + this.checkFolder(); + let folder = path_1.default.join(this.root, 'node_modules', name); + let stat = await util_1.promisify(fs_1.default.lstat)(folder); + if (stat.isSymbolicLink()) { + logger.info(`skipped update of ${name}`); + return false; + } + let version; + if (fs_1.default.existsSync(path_1.default.join(folder, 'package.json'))) { + let content = await util_1.promisify(fs_1.default.readFile)(path_1.default.join(folder, 'package.json'), 'utf8'); + version = JSON.parse(content).version; + } + logger.info(`Loading info of ${name}.`); + let info = await this.getInfo(uri ? uri : name); + if (version && info.version && semver_1.default.gte(version, info.version)) { + logger.info(`Extension ${name} is up to date.`); + return false; + } + let required = info['engines.coc'] ? info['engines.coc'].replace(/^\^/, '>=') : ''; + if (required && !semver_1.default.satisfies(workspace_1.default.version, required)) { + throw new Error(`${name} ${info.version} requires coc.nvim >= ${required}, please update coc.nvim.`); + } + await this._install(npm, uri ? uri : name, info, msg => { logger.info(msg); }); + workspace_1.default.showMessage(`Updated extension: ${name} to ${info.version}`, 'more'); + logger.info(`Update extension: ${name}`); + return true; + } + async getInfoFromUri(uri) { + if (uri.indexOf('github.com') == -1) + return; + uri = uri.replace(/\/$/, ''); + let fileUrl = uri.replace('github.com', 'raw.githubusercontent.com') + '/master/package.json'; + let content = await fetch_1.default(fileUrl); + let obj = typeof content == 'string' ? JSON.parse(content) : content; + return { + 'dist.tarball': `${uri}/archive/master.tar.gz`, + 'engines.coc': obj['engines'] ? obj['engines']['coc'] : undefined, + name: obj.name, + version: obj.version + }; } - } - - this.cache[abs] = entries - return cb(null, entries) -} - -Glob.prototype._readdirError = function (f, er, cb) { - if (this.aborted) - return - - // handle errors, and cache the information - switch (er.code) { - case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 - case 'ENOTDIR': // totally normal. means it *does* exist. - this.cache[this._makeAbs(f)] = 'FILE' - break - - case 'ENOENT': // not terribly unusual - case 'ELOOP': - case 'ENAMETOOLONG': - case 'UNKNOWN': - this.cache[this._makeAbs(f)] = false - break - - default: // some unusual error. Treat as failure. - this.cache[this._makeAbs(f)] = false - if (this.strict) { - this.emit('error', er) - // If the error is handled, then we abort - // if not, we threw out of here - this.abort() - } - if (!this.silent) - console.error('glob error', er) - break - } - - return cb() -} - -Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) { - var self = this - this._readdir(abs, inGlobStar, function (er, entries) { - self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb) - }) } +exports.default = ExtensionManager; +//# sourceMappingURL=extension.js.map +/***/ }), +/* 257 */ +/***/ (function(module, exports, __webpack_require__) { -Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { - //console.error('pgs2', prefix, remain[0], entries) - - // no entries means not a dir, so it can never have matches - // foo.txt/** doesn't match foo.txt - if (!entries) - return cb() - - // test without the globstar, and with every child both below - // and replacing the globstar. - var remainWithoutGlobStar = remain.slice(1) - var gspref = prefix ? [ prefix ] : [] - var noGlobStar = gspref.concat(remainWithoutGlobStar) - - // the noGlobStar pattern exits the inGlobStar state - this._process(noGlobStar, index, false, cb) - - var isSym = this.symlinks[abs] - var len = entries.length - - // If it's a symlink, and we're in a globstar, then stop - if (isSym && inGlobStar) - return cb() - - for (var i = 0; i < len; i++) { - var e = entries[i] - if (e.charAt(0) === '.' && !this.dot) - continue +var fs = __webpack_require__(4); +var ncp = __webpack_require__(258).ncp; +var path = __webpack_require__(20); +var rimraf = __webpack_require__(259); +var mkdirp = __webpack_require__(182); - // these two cases enter the inGlobStar state - var instead = gspref.concat(entries[i], remainWithoutGlobStar) - this._process(instead, index, true, cb) +module.exports = mv; - var below = gspref.concat(entries[i], remain) - this._process(below, index, true, cb) +function mv(source, dest, options, cb){ + if (typeof options === 'function') { + cb = options; + options = {}; } + var shouldMkdirp = !!options.mkdirp; + var clobber = options.clobber !== false; + var limit = options.limit || 16; - cb() -} - -Glob.prototype._processSimple = function (prefix, index, cb) { - // XXX review this. Shouldn't it be doing the mounting etc - // before doing stat? kinda weird? - var self = this - this._stat(prefix, function (er, exists) { - self._processSimple2(prefix, index, er, exists, cb) - }) -} -Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) { - - //console.error('ps2', prefix, exists) - - if (!this.matches[index]) - this.matches[index] = Object.create(null) - - // If it doesn't exist, then just mark the lack of results - if (!exists) - return cb() - - if (prefix && isAbsolute(prefix) && !this.nomount) { - var trail = /[\/\\]$/.test(prefix) - if (prefix.charAt(0) === '/') { - prefix = path.join(this.root, prefix) - } else { - prefix = path.resolve(this.root, prefix) - if (trail) - prefix += '/' - } + if (shouldMkdirp) { + mkdirs(); + } else { + doRename(); } - if (process.platform === 'win32') - prefix = prefix.replace(/\\/g, '/') - - // Mark this as a match - this._emitMatch(index, prefix) - cb() -} - -// Returns either 'DIR', 'FILE', or false -Glob.prototype._stat = function (f, cb) { - var abs = this._makeAbs(f) - var needDir = f.slice(-1) === '/' - - if (f.length > this.maxLength) - return cb() - - if (!this.stat && ownProp(this.cache, abs)) { - var c = this.cache[abs] - - if (Array.isArray(c)) - c = 'DIR' - - // It exists, but maybe not how we need it - if (!needDir || c === 'DIR') - return cb(null, c) - - if (needDir && c === 'FILE') - return cb() - - // otherwise we have to stat, because maybe c=true - // if we know it exists, but not what it is. + function mkdirs() { + mkdirp(path.dirname(dest), function(err) { + if (err) return cb(err); + doRename(); + }); } - var exists - var stat = this.statCache[abs] - if (stat !== undefined) { - if (stat === false) - return cb(null, stat) - else { - var type = stat.isDirectory() ? 'DIR' : 'FILE' - if (needDir && type === 'FILE') - return cb() - else - return cb(null, type, stat) + function doRename() { + if (clobber) { + fs.rename(source, dest, function(err) { + if (!err) return cb(); + if (err.code !== 'EXDEV') return cb(err); + moveFileAcrossDevice(source, dest, clobber, limit, cb); + }); + } else { + fs.link(source, dest, function(err) { + if (err) { + if (err.code === 'EXDEV') { + moveFileAcrossDevice(source, dest, clobber, limit, cb); + return; + } + if (err.code === 'EISDIR' || err.code === 'EPERM') { + moveDirAcrossDevice(source, dest, clobber, limit, cb); + return; + } + cb(err); + return; + } + fs.unlink(source, cb); + }); } } +} - var self = this - var statcb = inflight('stat\0' + abs, lstatcb_) - if (statcb) - fs.lstat(abs, statcb) - - function lstatcb_ (er, lstat) { - if (lstat && lstat.isSymbolicLink()) { - // If it's a symlink, then treat it as the target, unless - // the target does not exist, then treat it as a file. - return fs.stat(abs, function (er, stat) { - if (er) - self._stat2(f, abs, null, lstat, cb) - else - self._stat2(f, abs, er, stat, cb) - }) +function moveFileAcrossDevice(source, dest, clobber, limit, cb) { + var outFlags = clobber ? 'w' : 'wx'; + var ins = fs.createReadStream(source); + var outs = fs.createWriteStream(dest, {flags: outFlags}); + ins.on('error', function(err){ + ins.destroy(); + outs.destroy(); + outs.removeListener('close', onClose); + if (err.code === 'EISDIR' || err.code === 'EPERM') { + moveDirAcrossDevice(source, dest, clobber, limit, cb); } else { - self._stat2(f, abs, er, lstat, cb) + cb(err); } + }); + outs.on('error', function(err){ + ins.destroy(); + outs.destroy(); + outs.removeListener('close', onClose); + cb(err); + }); + outs.once('close', onClose); + ins.pipe(outs); + function onClose(){ + fs.unlink(source, cb); } } -Glob.prototype._stat2 = function (f, abs, er, stat, cb) { - if (er) { - this.statCache[abs] = false - return cb() +function moveDirAcrossDevice(source, dest, clobber, limit, cb) { + var options = { + stopOnErr: true, + clobber: false, + limit: limit, + }; + if (clobber) { + rimraf(dest, { disableGlob: true }, function(err) { + if (err) return cb(err); + startNcp(); + }); + } else { + startNcp(); + } + function startNcp() { + ncp(source, dest, options, function(errList) { + if (errList) return cb(errList[0]); + rimraf(source, { disableGlob: true }, cb); + }); } - - var needDir = f.slice(-1) === '/' - this.statCache[abs] = stat - - if (abs.slice(-1) === '/' && !stat.isDirectory()) - return cb(null, false, stat) - - var c = stat.isDirectory() ? 'DIR' : 'FILE' - this.cache[abs] = this.cache[abs] || c - - if (needDir && c !== 'DIR') - return cb() - - return cb(null, c, stat) } /***/ }), -/* 259 */ +/* 258 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = globSync -globSync.GlobSync = GlobSync - -var fs = __webpack_require__(4) -var minimatch = __webpack_require__(204) -var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(258).Glob -var util = __webpack_require__(12) -var path = __webpack_require__(20) -var assert = __webpack_require__(46) -var isAbsolute = __webpack_require__(240) -var common = __webpack_require__(260) -var alphasort = common.alphasort -var alphasorti = common.alphasorti -var setopts = common.setopts -var ownProp = common.ownProp -var childrenIgnored = common.childrenIgnored - -function globSync (pattern, options) { - if (typeof options === 'function' || arguments.length === 3) - throw new TypeError('callback provided to sync glob\n'+ - 'See: https://github.com/isaacs/node-glob/issues/167') - - return new GlobSync(pattern, options).found -} - -function GlobSync (pattern, options) { - if (!pattern) - throw new Error('must provide pattern') +var fs = __webpack_require__(4), + path = __webpack_require__(20); - if (typeof options === 'function' || arguments.length === 3) - throw new TypeError('callback provided to sync glob\n'+ - 'See: https://github.com/isaacs/node-glob/issues/167') +module.exports = ncp; +ncp.ncp = ncp; - if (!(this instanceof GlobSync)) - return new GlobSync(pattern, options) +function ncp (source, dest, options, callback) { + var cback = callback; - setopts(this, pattern, options) + if (!callback) { + cback = options; + options = {}; + } - if (this.noprocess) - return this + var basePath = process.cwd(), + currentPath = path.resolve(basePath, source), + targetPath = path.resolve(basePath, dest), + filter = options.filter, + rename = options.rename, + transform = options.transform, + clobber = options.clobber !== false, + modified = options.modified, + dereference = options.dereference, + errs = null, + started = 0, + finished = 0, + running = 0, + limit = options.limit || ncp.limit || 16; - var n = this.minimatch.set.length - this.matches = new Array(n) - for (var i = 0; i < n; i ++) { - this._process(this.minimatch.set[i], i, false) - } - this._finish() -} + limit = (limit < 1) ? 1 : (limit > 512) ? 512 : limit; -GlobSync.prototype._finish = function () { - assert(this instanceof GlobSync) - if (this.realpath) { - var self = this - this.matches.forEach(function (matchset, index) { - var set = self.matches[index] = Object.create(null) - for (var p in matchset) { - try { - p = self._makeAbs(p) - var real = fs.realpathSync(p, self.realpathCache) - set[real] = true - } catch (er) { - if (er.syscall === 'stat') - set[self._makeAbs(p)] = true - else - throw er + startCopy(currentPath); + + function startCopy(source) { + started++; + if (filter) { + if (filter instanceof RegExp) { + if (!filter.test(source)) { + return cb(true); } } - }) + else if (typeof filter === 'function') { + if (!filter(source)) { + return cb(true); + } + } + } + return getStats(source); } - common.finish(this) -} + function getStats(source) { + var stat = dereference ? fs.stat : fs.lstat; + if (running >= limit) { + return setImmediate(function () { + getStats(source); + }); + } + running++; + stat(source, function (err, stats) { + var item = {}; + if (err) { + return onError(err); + } -GlobSync.prototype._process = function (pattern, index, inGlobStar) { - assert(this instanceof GlobSync) + // We need to get the mode from the stats object and preserve it. + item.name = source; + item.mode = stats.mode; + item.mtime = stats.mtime; //modified time + item.atime = stats.atime; //access time - // Get the first [n] parts of pattern that are all strings. - var n = 0 - while (typeof pattern[n] === 'string') { - n ++ + if (stats.isDirectory()) { + return onDir(item); + } + else if (stats.isFile()) { + return onFile(item); + } + else if (stats.isSymbolicLink()) { + // Symlinks don't really need to know about the mode. + return onLink(source); + } + }); } - // now n is the index of the first one that is *not* a string. - - // See if there's anything else - var prefix - switch (n) { - // if not, then this is rather simple - case pattern.length: - this._processSimple(pattern.join('/'), index) - return - - case 0: - // pattern *starts* with some non-trivial item. - // going to readdir(cwd), but not include the prefix in matches. - prefix = null - break - default: - // pattern has some string bits in the front. - // whatever it starts with, whether that's 'absolute' like /foo/bar, - // or 'relative' like '../baz' - prefix = pattern.slice(0, n).join('/') - break + function onFile(file) { + var target = file.name.replace(currentPath, targetPath); + if(rename) { + target = rename(target); + } + isWritable(target, function (writable) { + if (writable) { + return copyFile(file, target); + } + if(clobber) { + rmFile(target, function () { + copyFile(file, target); + }); + } + if (modified) { + var stat = dereference ? fs.stat : fs.lstat; + stat(target, function(err, stats) { + //if souce modified time greater to target modified time copy file + if (file.mtime.getTime()>stats.mtime.getTime()) + copyFile(file, target); + else return cb(); + }); + } + else { + return cb(); + } + }); } - var remain = pattern.slice(n) - - // get the list of entries. - var read - if (prefix === null) - read = '.' - else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { - if (!prefix || !isAbsolute(prefix)) - prefix = '/' + prefix - read = prefix - } else - read = prefix - - var abs = this._makeAbs(read) - - //if ignored, skip processing - if (childrenIgnored(this, read)) - return - - var isGlobStar = remain[0] === minimatch.GLOBSTAR - if (isGlobStar) - this._processGlobStar(prefix, read, abs, remain, index, inGlobStar) - else - this._processReaddir(prefix, read, abs, remain, index, inGlobStar) -} - - -GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) { - var entries = this._readdir(abs, inGlobStar) + function copyFile(file, target) { + var readStream = fs.createReadStream(file.name), + writeStream = fs.createWriteStream(target, { mode: file.mode }); + + readStream.on('error', onError); + writeStream.on('error', onError); + + if(transform) { + transform(readStream, writeStream, file); + } else { + writeStream.on('open', function() { + readStream.pipe(writeStream); + }); + } + writeStream.once('finish', function() { + if (modified) { + //target file modified date sync. + fs.utimesSync(target, file.atime, file.mtime); + cb(); + } + else cb(); + }); + } - // if the abs isn't a dir, then nothing can match! - if (!entries) - return + function rmFile(file, done) { + fs.unlink(file, function (err) { + if (err) { + return onError(err); + } + return done(); + }); + } - // It will only match dot entries if it starts with a dot, or if - // dot is set. Stuff like @(.foo|.bar) isn't allowed. - var pn = remain[0] - var negate = !!this.minimatch.negate - var rawGlob = pn._glob - var dotOk = this.dot || rawGlob.charAt(0) === '.' + function onDir(dir) { + var target = dir.name.replace(currentPath, targetPath); + isWritable(target, function (writable) { + if (writable) { + return mkDir(dir, target); + } + copyDir(dir.name); + }); + } - var matchedEntries = [] - for (var i = 0; i < entries.length; i++) { - var e = entries[i] - if (e.charAt(0) !== '.' || dotOk) { - var m - if (negate && !prefix) { - m = !e.match(pn) - } else { - m = e.match(pn) + function mkDir(dir, target) { + fs.mkdir(target, dir.mode, function (err) { + if (err) { + return onError(err); } - if (m) - matchedEntries.push(e) - } + copyDir(dir.name); + }); } - var len = matchedEntries.length - // If there are no matched entries, then nothing matches. - if (len === 0) - return + function copyDir(dir) { + fs.readdir(dir, function (err, items) { + if (err) { + return onError(err); + } + items.forEach(function (item) { + startCopy(path.join(dir, item)); + }); + return cb(); + }); + } - // if this is the last remaining pattern bit, then no need for - // an additional stat *unless* the user has specified mark or - // stat explicitly. We know they exist, since readdir returned - // them. + function onLink(link) { + var target = link.replace(currentPath, targetPath); + fs.readlink(link, function (err, resolvedPath) { + if (err) { + return onError(err); + } + checkLink(resolvedPath, target); + }); + } - if (remain.length === 1 && !this.mark && !this.stat) { - if (!this.matches[index]) - this.matches[index] = Object.create(null) + function checkLink(resolvedPath, target) { + if (dereference) { + resolvedPath = path.resolve(basePath, resolvedPath); + } + isWritable(target, function (writable) { + if (writable) { + return makeLink(resolvedPath, target); + } + fs.readlink(target, function (err, targetDest) { + if (err) { + return onError(err); + } + if (dereference) { + targetDest = path.resolve(basePath, targetDest); + } + if (targetDest === resolvedPath) { + return cb(); + } + return rmFile(target, function () { + makeLink(resolvedPath, target); + }); + }); + }); + } - for (var i = 0; i < len; i ++) { - var e = matchedEntries[i] - if (prefix) { - if (prefix.slice(-1) !== '/') - e = prefix + '/' + e - else - e = prefix + e + function makeLink(linkPath, target) { + fs.symlink(linkPath, target, function (err) { + if (err) { + return onError(err); } + return cb(); + }); + } - if (e.charAt(0) === '/' && !this.nomount) { - e = path.join(this.root, e) + function isWritable(path, done) { + fs.lstat(path, function (err) { + if (err) { + if (err.code === 'ENOENT') return done(true); + return done(false); } - this.matches[index][e] = true + return done(false); + }); + } + + function onError(err) { + if (options.stopOnError) { + return cback(err); } - // This was the last one, and no stats were needed - return + else if (!errs && options.errs) { + errs = fs.createWriteStream(options.errs); + } + else if (!errs) { + errs = []; + } + if (typeof errs.write === 'undefined') { + errs.push(err); + } + else { + errs.write(err.stack + '\n\n'); + } + return cb(); } - // now test all matched entries as stand-ins for that part - // of the pattern. - remain.shift() - for (var i = 0; i < len; i ++) { - var e = matchedEntries[i] - var newPattern - if (prefix) - newPattern = [prefix, e] - else - newPattern = [e] - this._process(newPattern.concat(remain), index, inGlobStar) + function cb(skipped) { + if (!skipped) running--; + finished++; + if ((started === finished) && (running === 0)) { + if (cback !== undefined ) { + return errs ? cback(errs) : cback(null); + } + } } } -GlobSync.prototype._emitMatch = function (index, e) { - var abs = this._makeAbs(e) - if (this.mark) - e = this._mark(e) - if (this.matches[index][e]) - return - if (this.nodir) { - var c = this.cache[this._makeAbs(e)] - if (c === 'DIR' || Array.isArray(c)) - return - } +/***/ }), +/* 259 */ +/***/ (function(module, exports, __webpack_require__) { - this.matches[index][e] = true - if (this.stat) - this._stat(e) -} +module.exports = rimraf +rimraf.sync = rimrafSync +var assert = __webpack_require__(46) +var path = __webpack_require__(20) +var fs = __webpack_require__(4) +var glob = __webpack_require__(260) -GlobSync.prototype._readdirInGlobStar = function (abs) { - // follow all symlinked directories forever - // just proceed as if this is a non-globstar situation - if (this.follow) - return this._readdir(abs, false) +var globOpts = { + nosort: true, + nocomment: true, + nonegate: true, + silent: true +} - var entries - var lstat - var stat - try { - lstat = fs.lstatSync(abs) - } catch (er) { - // lstat failed, doesn't exist - return null - } +// for EMFILE handling +var timeout = 0 - var isSym = lstat.isSymbolicLink() - this.symlinks[abs] = isSym +var isWindows = (process.platform === "win32") - // If it's not a symlink or a dir, then it's definitely a regular file. - // don't bother doing a readdir in that case. - if (!isSym && !lstat.isDirectory()) - this.cache[abs] = 'FILE' - else - entries = this._readdir(abs, false) +function defaults (options) { + var methods = [ + 'unlink', + 'chmod', + 'stat', + 'lstat', + 'rmdir', + 'readdir' + ] + methods.forEach(function(m) { + options[m] = options[m] || fs[m] + m = m + 'Sync' + options[m] = options[m] || fs[m] + }) - return entries + options.maxBusyTries = options.maxBusyTries || 3 + options.emfileWait = options.emfileWait || 1000 + options.disableGlob = options.disableGlob || false } -GlobSync.prototype._readdir = function (abs, inGlobStar) { - var entries +function rimraf (p, options, cb) { + if (typeof options === 'function') { + cb = options + options = {} + } - if (inGlobStar && !ownProp(this.symlinks, abs)) - return this._readdirInGlobStar(abs) + assert(p, 'rimraf: missing path') + assert.equal(typeof p, 'string', 'rimraf: path should be a string') + assert(options, 'rimraf: missing options') + assert.equal(typeof options, 'object', 'rimraf: options should be object') + assert.equal(typeof cb, 'function', 'rimraf: callback function required') - if (ownProp(this.cache, abs)) { - var c = this.cache[abs] - if (!c || c === 'FILE') - return null + defaults(options) - if (Array.isArray(c)) - return c - } + var busyTries = 0 + var errState = null + var n = 0 - try { - return this._readdirEntries(abs, fs.readdirSync(abs)) - } catch (er) { - this._readdirError(abs, er) - return null - } -} + if (options.disableGlob || !glob.hasMagic(p)) + return afterGlob(null, [p]) -GlobSync.prototype._readdirEntries = function (abs, entries) { - // if we haven't asked to stat everything, then just - // assume that everything in there exists, so we can avoid - // having to stat it a second time. - if (!this.mark && !this.stat) { - for (var i = 0; i < entries.length; i ++) { - var e = entries[i] - if (abs === '/') - e = abs + e - else - e = abs + '/' + e - this.cache[e] = true - } + fs.lstat(p, function (er, stat) { + if (!er) + return afterGlob(null, [p]) + + glob(p, globOpts, afterGlob) + }) + + function next (er) { + errState = errState || er + if (--n === 0) + cb(errState) } - this.cache[abs] = entries + function afterGlob (er, results) { + if (er) + return cb(er) - // mark and cache dir-ness - return entries -} + n = results.length + if (n === 0) + return cb() -GlobSync.prototype._readdirError = function (f, er) { - // handle errors, and cache the information - switch (er.code) { - case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 - case 'ENOTDIR': // totally normal. means it *does* exist. - this.cache[this._makeAbs(f)] = 'FILE' - break + results.forEach(function (p) { + rimraf_(p, options, function CB (er) { + if (er) { + if (isWindows && (er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") && + busyTries < options.maxBusyTries) { + busyTries ++ + var time = busyTries * 100 + // try again, with the same exact callback as this one. + return setTimeout(function () { + rimraf_(p, options, CB) + }, time) + } - case 'ENOENT': // not terribly unusual - case 'ELOOP': - case 'ENAMETOOLONG': - case 'UNKNOWN': - this.cache[this._makeAbs(f)] = false - break + // this one won't happen if graceful-fs is used. + if (er.code === "EMFILE" && timeout < options.emfileWait) { + return setTimeout(function () { + rimraf_(p, options, CB) + }, timeout ++) + } - default: // some unusual error. Treat as failure. - this.cache[this._makeAbs(f)] = false - if (this.strict) - throw er - if (!this.silent) - console.error('glob error', er) - break + // already gone + if (er.code === "ENOENT") er = null + } + + timeout = 0 + next(er) + }) + }) } } -GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) { +// Two possible strategies. +// 1. Assume it's a file. unlink it, then do the dir stuff on EPERM or EISDIR +// 2. Assume it's a directory. readdir, then do the file stuff on ENOTDIR +// +// Both result in an extra syscall when you guess wrong. However, there +// are likely far more normal files in the world than directories. This +// is based on the assumption that a the average number of files per +// directory is >= 1. +// +// If anyone ever complains about this, then I guess the strategy could +// be made configurable somehow. But until then, YAGNI. +function rimraf_ (p, options, cb) { + assert(p) + assert(options) + assert(typeof cb === 'function') - var entries = this._readdir(abs, inGlobStar) + // sunos lets the root user unlink directories, which is... weird. + // so we have to lstat here and make sure it's not a dir. + options.lstat(p, function (er, st) { + if (er && er.code === "ENOENT") + return cb(null) - // no entries means not a dir, so it can never have matches - // foo.txt/** doesn't match foo.txt - if (!entries) - return + if (st && st.isDirectory()) + return rmdir(p, options, er, cb) - // test without the globstar, and with every child both below - // and replacing the globstar. - var remainWithoutGlobStar = remain.slice(1) - var gspref = prefix ? [ prefix ] : [] - var noGlobStar = gspref.concat(remainWithoutGlobStar) - - // the noGlobStar pattern exits the inGlobStar state - this._process(noGlobStar, index, false) - - var len = entries.length - var isSym = this.symlinks[abs] - - // If it's a symlink, and we're in a globstar, then stop - if (isSym && inGlobStar) - return - - for (var i = 0; i < len; i++) { - var e = entries[i] - if (e.charAt(0) === '.' && !this.dot) - continue - - // these two cases enter the inGlobStar state - var instead = gspref.concat(entries[i], remainWithoutGlobStar) - this._process(instead, index, true) - - var below = gspref.concat(entries[i], remain) - this._process(below, index, true) - } + options.unlink(p, function (er) { + if (er) { + if (er.code === "ENOENT") + return cb(null) + if (er.code === "EPERM") + return (isWindows) + ? fixWinEPERM(p, options, er, cb) + : rmdir(p, options, er, cb) + if (er.code === "EISDIR") + return rmdir(p, options, er, cb) + } + return cb(er) + }) + }) } -GlobSync.prototype._processSimple = function (prefix, index) { - // XXX review this. Shouldn't it be doing the mounting etc - // before doing stat? kinda weird? - var exists = this._stat(prefix) +function fixWinEPERM (p, options, er, cb) { + assert(p) + assert(options) + assert(typeof cb === 'function') + if (er) + assert(er instanceof Error) - if (!this.matches[index]) - this.matches[index] = Object.create(null) + options.chmod(p, 666, function (er2) { + if (er2) + cb(er2.code === "ENOENT" ? null : er) + else + options.stat(p, function(er3, stats) { + if (er3) + cb(er3.code === "ENOENT" ? null : er) + else if (stats.isDirectory()) + rmdir(p, options, er, cb) + else + options.unlink(p, cb) + }) + }) +} - // If it doesn't exist, then just mark the lack of results - if (!exists) - return +function fixWinEPERMSync (p, options, er) { + assert(p) + assert(options) + if (er) + assert(er instanceof Error) - if (prefix && isAbsolute(prefix) && !this.nomount) { - var trail = /[\/\\]$/.test(prefix) - if (prefix.charAt(0) === '/') { - prefix = path.join(this.root, prefix) - } else { - prefix = path.resolve(this.root, prefix) - if (trail) - prefix += '/' - } + try { + options.chmodSync(p, 666) + } catch (er2) { + if (er2.code === "ENOENT") + return + else + throw er } - if (process.platform === 'win32') - prefix = prefix.replace(/\\/g, '/') + try { + var stats = options.statSync(p) + } catch (er3) { + if (er3.code === "ENOENT") + return + else + throw er + } - // Mark this as a match - this.matches[index][prefix] = true + if (stats.isDirectory()) + rmdirSync(p, options, er) + else + options.unlinkSync(p) } -// Returns either 'DIR', 'FILE', or false -GlobSync.prototype._stat = function (f) { - var abs = this._makeAbs(f) - var needDir = f.slice(-1) === '/' +function rmdir (p, options, originalEr, cb) { + assert(p) + assert(options) + if (originalEr) + assert(originalEr instanceof Error) + assert(typeof cb === 'function') - if (f.length > this.maxLength) - return false + // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS) + // if we guessed wrong, and it's not a directory, then + // raise the original error. + options.rmdir(p, function (er) { + if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM")) + rmkids(p, options, cb) + else if (er && er.code === "ENOTDIR") + cb(originalEr) + else + cb(er) + }) +} - if (!this.stat && ownProp(this.cache, abs)) { - var c = this.cache[abs] +function rmkids(p, options, cb) { + assert(p) + assert(options) + assert(typeof cb === 'function') - if (Array.isArray(c)) - c = 'DIR' + options.readdir(p, function (er, files) { + if (er) + return cb(er) + var n = files.length + if (n === 0) + return options.rmdir(p, cb) + var errState + files.forEach(function (f) { + rimraf(path.join(p, f), options, function (er) { + if (errState) + return + if (er) + return cb(errState = er) + if (--n === 0) + options.rmdir(p, cb) + }) + }) + }) +} - // It exists, but maybe not how we need it - if (!needDir || c === 'DIR') - return c +// this looks simpler, and is strictly *faster*, but will +// tie up the JavaScript thread and fail on excessively +// deep directory trees. +function rimrafSync (p, options) { + options = options || {} + defaults(options) - if (needDir && c === 'FILE') - return false + assert(p, 'rimraf: missing path') + assert.equal(typeof p, 'string', 'rimraf: path should be a string') + assert(options, 'rimraf: missing options') + assert.equal(typeof options, 'object', 'rimraf: options should be object') - // otherwise we have to stat, because maybe c=true - // if we know it exists, but not what it is. - } + var results - var exists - var stat = this.statCache[abs] - if (!stat) { - var lstat + if (options.disableGlob || !glob.hasMagic(p)) { + results = [p] + } else { try { - lstat = fs.lstatSync(abs) + fs.lstatSync(p) + results = [p] } catch (er) { - return false - } - - if (lstat.isSymbolicLink()) { - try { - stat = fs.statSync(abs) - } catch (er) { - stat = lstat - } - } else { - stat = lstat + results = glob.sync(p, globOpts) } } - this.statCache[abs] = stat + if (!results.length) + return - var c = stat.isDirectory() ? 'DIR' : 'FILE' - this.cache[abs] = this.cache[abs] || c + for (var i = 0; i < results.length; i++) { + var p = results[i] - if (needDir && c !== 'DIR') - return false + try { + var st = options.lstatSync(p) + } catch (er) { + if (er.code === "ENOENT") + return + } - return c + try { + // sunos lets the root user unlink directories, which is... weird. + if (st && st.isDirectory()) + rmdirSync(p, options, null) + else + options.unlinkSync(p) + } catch (er) { + if (er.code === "ENOENT") + return + if (er.code === "EPERM") + return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er) + if (er.code !== "EISDIR") + throw er + rmdirSync(p, options, er) + } + } } -GlobSync.prototype._mark = function (p) { - return common.mark(this, p) +function rmdirSync (p, options, originalEr) { + assert(p) + assert(options) + if (originalEr) + assert(originalEr instanceof Error) + + try { + options.rmdirSync(p) + } catch (er) { + if (er.code === "ENOENT") + return + if (er.code === "ENOTDIR") + throw originalEr + if (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM") + rmkidsSync(p, options) + } } -GlobSync.prototype._makeAbs = function (f) { - return common.makeAbs(this, f) +function rmkidsSync (p, options) { + assert(p) + assert(options) + options.readdirSync(p).forEach(function (f) { + rimrafSync(path.join(p, f), options) + }) + options.rmdirSync(p, options) } @@ -41340,11203 +41045,10418 @@ GlobSync.prototype._makeAbs = function (f) { /* 260 */ /***/ (function(module, exports, __webpack_require__) { -exports.alphasort = alphasort -exports.alphasorti = alphasorti -exports.setopts = setopts -exports.ownProp = ownProp -exports.makeAbs = makeAbs -exports.finish = finish -exports.mark = mark -exports.isIgnored = isIgnored -exports.childrenIgnored = childrenIgnored +// Approach: +// +// 1. Get the minimatch set +// 2. For each pattern in the set, PROCESS(pattern, false) +// 3. Store matches per-set, then uniq them +// +// PROCESS(pattern, inGlobStar) +// Get the first [n] items from pattern that are all strings +// Join these together. This is PREFIX. +// If there is no more remaining, then stat(PREFIX) and +// add to matches if it succeeds. END. +// +// If inGlobStar and PREFIX is symlink and points to dir +// set ENTRIES = [] +// else readdir(PREFIX) as ENTRIES +// If fail, END +// +// with ENTRIES +// If pattern[n] is GLOBSTAR +// // handle the case where the globstar match is empty +// // by pruning it out, and testing the resulting pattern +// PROCESS(pattern[0..n] + pattern[n+1 .. $], false) +// // handle other cases. +// for ENTRY in ENTRIES (not dotfiles) +// // attach globstar + tail onto the entry +// // Mark that this entry is a globstar match +// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true) +// +// else // not globstar +// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot) +// Test ENTRY against pattern[n] +// If fails, continue +// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $]) +// +// Caveat: +// Cache all stats and readdirs results to minimize syscall. Since all +// we ever care about is existence and directory-ness, we can just keep +// `true` for files, and [children,...] for directories, or `false` for +// things that don't exist. -function ownProp (obj, field) { - return Object.prototype.hasOwnProperty.call(obj, field) -} +module.exports = glob -var path = __webpack_require__(20) +var fs = __webpack_require__(4) var minimatch = __webpack_require__(204) -var isAbsolute = __webpack_require__(240) var Minimatch = minimatch.Minimatch +var inherits = __webpack_require__(238) +var EE = __webpack_require__(137).EventEmitter +var path = __webpack_require__(20) +var assert = __webpack_require__(46) +var isAbsolute = __webpack_require__(240) +var globSync = __webpack_require__(261) +var common = __webpack_require__(262) +var alphasort = common.alphasort +var alphasorti = common.alphasorti +var setopts = common.setopts +var ownProp = common.ownProp +var inflight = __webpack_require__(243) +var util = __webpack_require__(12) +var childrenIgnored = common.childrenIgnored +var isIgnored = common.isIgnored -function alphasorti (a, b) { - return a.toLowerCase().localeCompare(b.toLowerCase()) -} +var once = __webpack_require__(245) -function alphasort (a, b) { - return a.localeCompare(b) +function glob (pattern, options, cb) { + if (typeof options === 'function') cb = options, options = {} + if (!options) options = {} + + if (options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return globSync(pattern, options) + } + + return new Glob(pattern, options, cb) } -function setupIgnores (self, options) { - self.ignore = options.ignore || [] +glob.sync = globSync +var GlobSync = glob.GlobSync = globSync.GlobSync - if (!Array.isArray(self.ignore)) - self.ignore = [self.ignore] +// old api surface +glob.glob = glob - if (self.ignore.length) { - self.ignore = self.ignore.map(ignoreMap) +function extend (origin, add) { + if (add === null || typeof add !== 'object') { + return origin } -} -// ignore patterns are always in dot:true mode. -function ignoreMap (pattern) { - var gmatcher = null - if (pattern.slice(-3) === '/**') { - var gpattern = pattern.replace(/(\/\*\*)+$/, '') - gmatcher = new Minimatch(gpattern, { dot: true }) + var keys = Object.keys(add) + var i = keys.length + while (i--) { + origin[keys[i]] = add[keys[i]] } + return origin +} - return { - matcher: new Minimatch(pattern, { dot: true }), - gmatcher: gmatcher +glob.hasMagic = function (pattern, options_) { + var options = extend({}, options_) + options.noprocess = true + + var g = new Glob(pattern, options) + var set = g.minimatch.set + if (set.length > 1) + return true + + for (var j = 0; j < set[0].length; j++) { + if (typeof set[0][j] !== 'string') + return true } + + return false } -function setopts (self, pattern, options) { - if (!options) - options = {} +glob.Glob = Glob +inherits(Glob, EE) +function Glob (pattern, options, cb) { + if (typeof options === 'function') { + cb = options + options = null + } - // base-matching: just use globstar for that. - if (options.matchBase && -1 === pattern.indexOf("/")) { - if (options.noglobstar) { - throw new Error("base matching requires globstar") - } - pattern = "**/" + pattern + if (options && options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return new GlobSync(pattern, options) } - self.silent = !!options.silent - self.pattern = pattern - self.strict = options.strict !== false - self.realpath = !!options.realpath - self.realpathCache = options.realpathCache || Object.create(null) - self.follow = !!options.follow - self.dot = !!options.dot - self.mark = !!options.mark - self.nodir = !!options.nodir - if (self.nodir) - self.mark = true - self.sync = !!options.sync - self.nounique = !!options.nounique - self.nonull = !!options.nonull - self.nosort = !!options.nosort - self.nocase = !!options.nocase - self.stat = !!options.stat - self.noprocess = !!options.noprocess + if (!(this instanceof Glob)) + return new Glob(pattern, options, cb) - self.maxLength = options.maxLength || Infinity - self.cache = options.cache || Object.create(null) - self.statCache = options.statCache || Object.create(null) - self.symlinks = options.symlinks || Object.create(null) + setopts(this, pattern, options) + this._didRealPath = false - setupIgnores(self, options) + // process each pattern in the minimatch set + var n = this.minimatch.set.length - self.changedCwd = false - var cwd = process.cwd() - if (!ownProp(options, "cwd")) - self.cwd = cwd - else { - self.cwd = options.cwd - self.changedCwd = path.resolve(options.cwd) !== cwd - } + // The matches are stored as {: true,...} so that + // duplicates are automagically pruned. + // Later, we do an Object.keys() on these. + // Keep them as a list so we can fill in when nonull is set. + this.matches = new Array(n) - self.root = options.root || path.resolve(self.cwd, "/") - self.root = path.resolve(self.root) - if (process.platform === "win32") - self.root = self.root.replace(/\\/g, "/") + if (typeof cb === 'function') { + cb = once(cb) + this.on('error', cb) + this.on('end', function (matches) { + cb(null, matches) + }) + } - self.nomount = !!options.nomount + var self = this + var n = this.minimatch.set.length + this._processing = 0 + this.matches = new Array(n) - // disable comments and negation in Minimatch. - // Note that they are not supported in Glob itself anyway. - options.nonegate = true - options.nocomment = true + this._emitQueue = [] + this._processQueue = [] + this.paused = false - self.minimatch = new Minimatch(pattern, options) - self.options = self.minimatch.options -} + if (this.noprocess) + return this -function finish (self) { - var nou = self.nounique - var all = nou ? [] : Object.create(null) + if (n === 0) + return done() - for (var i = 0, l = self.matches.length; i < l; i ++) { - var matches = self.matches[i] - if (!matches || Object.keys(matches).length === 0) { - if (self.nonull) { - // do like the shell, and spit out the literal glob - var literal = self.minimatch.globSet[i] - if (nou) - all.push(literal) - else - all[literal] = true - } - } else { - // had matches - var m = Object.keys(matches) - if (nou) - all.push.apply(all, m) - else - m.forEach(function (m) { - all[m] = true - }) - } + for (var i = 0; i < n; i ++) { + this._process(this.minimatch.set[i], i, false, done) } - if (!nou) - all = Object.keys(all) + function done () { + --self._processing + if (self._processing <= 0) + self._finish() + } +} - if (!self.nosort) - all = all.sort(self.nocase ? alphasorti : alphasort) - - // at *some* point we statted all of these - if (self.mark) { - for (var i = 0; i < all.length; i++) { - all[i] = self._mark(all[i]) - } - if (self.nodir) { - all = all.filter(function (e) { - return !(/\/$/.test(e)) - }) - } - } +Glob.prototype._finish = function () { + assert(this instanceof Glob) + if (this.aborted) + return - if (self.ignore.length) - all = all.filter(function(m) { - return !isIgnored(self, m) - }) + if (this.realpath && !this._didRealpath) + return this._realpath() - self.found = all + common.finish(this) + this.emit('end', this.found) } -function mark (self, p) { - var abs = makeAbs(self, p) - var c = self.cache[abs] - var m = p - if (c) { - var isDir = c === 'DIR' || Array.isArray(c) - var slash = p.slice(-1) === '/' +Glob.prototype._realpath = function () { + if (this._didRealpath) + return - if (isDir && !slash) - m += '/' - else if (!isDir && slash) - m = m.slice(0, -1) + this._didRealpath = true - if (m !== p) { - var mabs = makeAbs(self, m) - self.statCache[mabs] = self.statCache[abs] - self.cache[mabs] = self.cache[abs] - } - } + var n = this.matches.length + if (n === 0) + return this._finish() - return m -} + var self = this + for (var i = 0; i < this.matches.length; i++) + this._realpathSet(i, next) -// lotta situps... -function makeAbs (self, f) { - var abs = f - if (f.charAt(0) === '/') { - abs = path.join(self.root, f) - } else if (isAbsolute(f) || f === '') { - abs = f - } else if (self.changedCwd) { - abs = path.resolve(self.cwd, f) - } else { - abs = path.resolve(f) + function next () { + if (--n === 0) + self._finish() } - return abs } +Glob.prototype._realpathSet = function (index, cb) { + var matchset = this.matches[index] + if (!matchset) + return cb() -// Return true, if pattern ends with globstar '**', for the accompanying parent directory. -// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents -function isIgnored (self, path) { - if (!self.ignore.length) - return false + var found = Object.keys(matchset) + var self = this + var n = found.length - return self.ignore.some(function(item) { - return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path)) - }) -} + if (n === 0) + return cb() -function childrenIgnored (self, path) { - if (!self.ignore.length) - return false + var set = this.matches[index] = Object.create(null) + found.forEach(function (p, i) { + // If there's a problem with the stat, then it means that + // one or more of the links in the realpath couldn't be + // resolved. just return the abs value in that case. + p = self._makeAbs(p) + fs.realpath(p, self.realpathCache, function (er, real) { + if (!er) + set[real] = true + else if (er.syscall === 'stat') + set[p] = true + else + self.emit('error', er) // srsly wtf right here - return self.ignore.some(function(item) { - return !!(item.gmatcher && item.gmatcher.match(path)) + if (--n === 0) { + self.matches[index] = set + cb() + } + }) }) } +Glob.prototype._mark = function (p) { + return common.mark(this, p) +} -/***/ }), -/* 261 */ -/***/ (function(module, exports, __webpack_require__) { - -var cc = __webpack_require__(262) -var join = __webpack_require__(20).join -var deepExtend = __webpack_require__(265) -var etc = '/etc' -var win = process.platform === "win32" -var home = win - ? process.env.USERPROFILE - : process.env.HOME - -module.exports = function (name, defaults, argv, parse) { - if('string' !== typeof name) - throw new Error('rc(name): name *must* be string') - if(!argv) - argv = __webpack_require__(266)(process.argv.slice(2)) - defaults = ( - 'string' === typeof defaults - ? cc.json(defaults) : defaults - ) || {} +Glob.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} - parse = parse || cc.parse +Glob.prototype.abort = function () { + this.aborted = true + this.emit('abort') +} - var env = cc.env(name + '_') +Glob.prototype.pause = function () { + if (!this.paused) { + this.paused = true + this.emit('pause') + } +} - var configs = [defaults] - var configFiles = [] - function addConfigFile (file) { - if (configFiles.indexOf(file) >= 0) return - var fileConfig = cc.file(file) - if (fileConfig) { - configs.push(parse(fileConfig)) - configFiles.push(file) +Glob.prototype.resume = function () { + if (this.paused) { + this.emit('resume') + this.paused = false + if (this._emitQueue.length) { + var eq = this._emitQueue.slice(0) + this._emitQueue.length = 0 + for (var i = 0; i < eq.length; i ++) { + var e = eq[i] + this._emitMatch(e[0], e[1]) + } + } + if (this._processQueue.length) { + var pq = this._processQueue.slice(0) + this._processQueue.length = 0 + for (var i = 0; i < pq.length; i ++) { + var p = pq[i] + this._processing-- + this._process(p[0], p[1], p[2], p[3]) + } } } +} - // which files do we look at? - if (!win) - [join(etc, name, 'config'), - join(etc, name + 'rc')].forEach(addConfigFile) - if (home) - [join(home, '.config', name, 'config'), - join(home, '.config', name), - join(home, '.' + name, 'config'), - join(home, '.' + name + 'rc')].forEach(addConfigFile) - addConfigFile(cc.find('.'+name+'rc')) - if (env.config) addConfigFile(env.config) - if (argv.config) addConfigFile(argv.config) +Glob.prototype._process = function (pattern, index, inGlobStar, cb) { + assert(this instanceof Glob) + assert(typeof cb === 'function') - return deepExtend.apply(null, configs.concat([ - env, - argv, - configFiles.length ? {configs: configFiles, config: configFiles[configFiles.length - 1]} : undefined, - ])) -} + if (this.aborted) + return + this._processing++ + if (this.paused) { + this._processQueue.push([pattern, index, inGlobStar, cb]) + return + } -/***/ }), -/* 262 */ -/***/ (function(module, exports, __webpack_require__) { + //console.error('PROCESS %d', this._processing, pattern) -"use strict"; + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n ++ + } + // now n is the index of the first one that is *not* a string. -var fs = __webpack_require__(4) -var ini = __webpack_require__(263) -var path = __webpack_require__(20) -var stripJsonComments = __webpack_require__(264) + // see if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index, cb) + return -var parse = exports.parse = function (content) { + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break - //if it ends in .json or starts with { then it must be json. - //must be done this way, because ini accepts everything. - //can't just try and parse it and let it throw if it's not ini. - //everything is ini. even json with a syntax error. + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } - if(/^\s*{/.test(content)) - return JSON.parse(stripJsonComments(content)) - return ini.parse(content) + var remain = pattern.slice(n) -} + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix -var file = exports.file = function () { - var args = [].slice.call(arguments).filter(function (arg) { return arg != null }) + var abs = this._makeAbs(read) - //path.join breaks if it's a not a string, so just skip this. - for(var i in args) - if('string' !== typeof args[i]) - return + //if ignored, skip _processing + if (childrenIgnored(this, read)) + return cb() - var file = path.join.apply(null, args) - var content - try { - return fs.readFileSync(file,'utf-8') - } catch (err) { - return - } + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb) } -var json = exports.json = function () { - var content = file.apply(null, arguments) - return content ? parse(content) : null +Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) } -var env = exports.env = function (prefix, env) { - env = env || process.env - var obj = {} - var l = prefix.length - for(var k in env) { - if(k.toLowerCase().indexOf(prefix.toLowerCase()) === 0) { - - var keypath = k.substring(l).split('__') +Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { - // Trim empty strings from keypath array - var _emptyStringIndex - while ((_emptyStringIndex=keypath.indexOf('')) > -1) { - keypath.splice(_emptyStringIndex, 1) - } + // if the abs isn't a dir, then nothing can match! + if (!entries) + return cb() - var cursor = obj - keypath.forEach(function _buildSubObj(_subkey,i){ + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' - // (check for _subkey first so we ignore empty strings) - // (check for cursor to avoid assignment to primitive objects) - if (!_subkey || typeof cursor !== 'object') - return + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) + } + } - // If this is the last key, just stuff the value in there - // Assigns actual value from env variable to final key - // (unless it's just an empty string- in that case use the last valid key) - if (i === keypath.length-1) - cursor[_subkey] = env[k] + //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries) + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return cb() - // Build sub-object if nothing already exists at the keypath - if (cursor[_subkey] === undefined) - cursor[_subkey] = {} + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. - // Increment cursor used to track the object at the current depth - cursor = cursor[_subkey] + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) - }) + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this._emitMatch(index, e) } - + // This was the last one, and no stats were needed + return cb() } - return obj -} - -var find = exports.find = function () { - var rel = path.join.apply(null, [].slice.call(arguments)) - - function find(start, rel) { - var file = path.join(start, rel) - try { - fs.statSync(file) - return file - } catch (err) { - if(path.dirname(start) !== start) // root - return find(path.dirname(start), rel) + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + var newPattern + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e } + this._process([e].concat(remain), index, inGlobStar, cb) } - return find(process.cwd(), rel) + cb() } +Glob.prototype._emitMatch = function (index, e) { + if (this.aborted) + return + if (this.matches[index][e]) + return + if (isIgnored(this, e)) + return -/***/ }), -/* 263 */ -/***/ (function(module, exports) { + if (this.paused) { + this._emitQueue.push([index, e]) + return + } -exports.parse = exports.decode = decode + var abs = this._makeAbs(e) -exports.stringify = exports.encode = encode + if (this.nodir) { + var c = this.cache[abs] + if (c === 'DIR' || Array.isArray(c)) + return + } -exports.safe = safe -exports.unsafe = unsafe + if (this.mark) + e = this._mark(e) -var eol = typeof process !== 'undefined' && - process.platform === 'win32' ? '\r\n' : '\n' + this.matches[index][e] = true -function encode (obj, opt) { - var children = [] - var out = '' + var st = this.statCache[abs] + if (st) + this.emit('stat', e, st) - if (typeof opt === 'string') { - opt = { - section: opt, - whitespace: false - } - } else { - opt = opt || {} - opt.whitespace = opt.whitespace === true - } + this.emit('match', e) +} - var separator = opt.whitespace ? ' = ' : '=' +Glob.prototype._readdirInGlobStar = function (abs, cb) { + if (this.aborted) + return - Object.keys(obj).forEach(function (k, _, __) { - var val = obj[k] - if (val && Array.isArray(val)) { - val.forEach(function (item) { - out += safe(k + '[]') + separator + safe(item) + '\n' - }) - } else if (val && typeof val === 'object') { - children.push(k) - } else { - out += safe(k) + separator + safe(val) + eol - } - }) + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false, cb) - if (opt.section && out.length) { - out = '[' + safe(opt.section) + ']' + eol + out - } + var lstatkey = 'lstat\0' + abs + var self = this + var lstatcb = inflight(lstatkey, lstatcb_) - children.forEach(function (k, _, __) { - var nk = dotSplit(k).join('\\.') - var section = (opt.section ? opt.section + '.' : '') + nk - var child = encode(obj[k], { - section: section, - whitespace: opt.whitespace - }) - if (out.length && child.length) { - out += eol - } - out += child - }) + if (lstatcb) + fs.lstat(abs, lstatcb) - return out -} + function lstatcb_ (er, lstat) { + if (er) + return cb() -function dotSplit (str) { - return str.replace(/\1/g, '\u0002LITERAL\\1LITERAL\u0002') - .replace(/\\\./g, '\u0001') - .split(/\./).map(function (part) { - return part.replace(/\1/g, '\\.') - .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001') - }) + var isSym = lstat.isSymbolicLink() + self.symlinks[abs] = isSym + + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && !lstat.isDirectory()) { + self.cache[abs] = 'FILE' + cb() + } else + self._readdir(abs, false, cb) + } } -function decode (str) { - var out = {} - var p = out - var section = null - // section |key = value - var re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i - var lines = str.split(/[\r\n]+/g) +Glob.prototype._readdir = function (abs, inGlobStar, cb) { + if (this.aborted) + return - lines.forEach(function (line, _, __) { - if (!line || line.match(/^\s*[;#]/)) return - var match = line.match(re) - if (!match) return - if (match[1] !== undefined) { - section = unsafe(match[1]) - p = out[section] = out[section] || {} - return - } - var key = unsafe(match[2]) - var value = match[3] ? unsafe(match[4]) : true - switch (value) { - case 'true': - case 'false': - case 'null': value = JSON.parse(value) - } + cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb) + if (!cb) + return - // Convert keys with '[]' suffix to an array - if (key.length > 2 && key.slice(-2) === '[]') { - key = key.substring(0, key.length - 2) - if (!p[key]) { - p[key] = [] - } else if (!Array.isArray(p[key])) { - p[key] = [p[key]] - } - } + //console.error('RD %j %j', +inGlobStar, abs) + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs, cb) - // safeguard against resetting a previously defined - // array by accidentally forgetting the brackets - if (Array.isArray(p[key])) { - p[key].push(value) - } else { - p[key] = value - } - }) + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return cb() - // {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}} - // use a filter to return the keys that have to be deleted. - Object.keys(out).filter(function (k, _, __) { - if (!out[k] || - typeof out[k] !== 'object' || - Array.isArray(out[k])) { - return false - } - // see if the parent section is also an object. - // if so, add it to that, and mark this one for deletion - var parts = dotSplit(k) - var p = out - var l = parts.pop() - var nl = l.replace(/\\\./g, '.') - parts.forEach(function (part, _, __) { - if (!p[part] || typeof p[part] !== 'object') p[part] = {} - p = p[part] - }) - if (p === out && nl === l) { - return false - } - p[nl] = out[k] - return true - }).forEach(function (del, _, __) { - delete out[del] - }) + if (Array.isArray(c)) + return cb(null, c) + } - return out + var self = this + fs.readdir(abs, readdirCb(this, abs, cb)) } -function isQuoted (val) { - return (val.charAt(0) === '"' && val.slice(-1) === '"') || - (val.charAt(0) === "'" && val.slice(-1) === "'") +function readdirCb (self, abs, cb) { + return function (er, entries) { + if (er) + self._readdirError(abs, er, cb) + else + self._readdirEntries(abs, entries, cb) + } } -function safe (val) { - return (typeof val !== 'string' || - val.match(/[=\r\n]/) || - val.match(/^\[/) || - (val.length > 1 && - isQuoted(val)) || - val !== val.trim()) - ? JSON.stringify(val) - : val.replace(/;/g, '\\;').replace(/#/g, '\\#') -} +Glob.prototype._readdirEntries = function (abs, entries, cb) { + if (this.aborted) + return -function unsafe (val, doUnesc) { - val = (val || '').trim() - if (isQuoted(val)) { - // remove the single quotes before calling JSON.parse - if (val.charAt(0) === "'") { - val = val.substr(1, val.length - 2) - } - try { val = JSON.parse(val) } catch (_) {} - } else { - // walk the val to find the first not-escaped ; character - var esc = false - var unesc = '' - for (var i = 0, l = val.length; i < l; i++) { - var c = val.charAt(i) - if (esc) { - if ('\\;#'.indexOf(c) !== -1) { - unesc += c - } else { - unesc += '\\' + c - } - esc = false - } else if (';#'.indexOf(c) !== -1) { - break - } else if (c === '\\') { - esc = true - } else { - unesc += c - } - } - if (esc) { - unesc += '\\' + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i ++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true } - return unesc.trim() } - return val + + this.cache[abs] = entries + return cb(null, entries) } +Glob.prototype._readdirError = function (f, er, cb) { + if (this.aborted) + return -/***/ }), -/* 264 */ -/***/ (function(module, exports, __webpack_require__) { + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + this.cache[this._makeAbs(f)] = 'FILE' + break -"use strict"; + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break -var singleComment = 1; -var multiComment = 2; + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) { + this.emit('error', er) + // If the error is handled, then we abort + // if not, we threw out of here + this.abort() + } + if (!this.silent) + console.error('glob error', er) + break + } -function stripWithoutWhitespace() { - return ''; + return cb() } -function stripWithWhitespace(str, start, end) { - return str.slice(start, end).replace(/\S/g, ' '); +Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) } -module.exports = function (str, opts) { - opts = opts || {}; - - var currentChar; - var nextChar; - var insideString = false; - var insideComment = false; - var offset = 0; - var ret = ''; - var strip = opts.whitespace === false ? stripWithoutWhitespace : stripWithWhitespace; - - for (var i = 0; i < str.length; i++) { - currentChar = str[i]; - nextChar = str[i + 1]; - if (!insideComment && currentChar === '"') { - var escaped = str[i - 1] === '\\' && str[i - 2] !== '\\'; - if (!escaped) { - insideString = !insideString; - } - } +Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { + //console.error('pgs2', prefix, remain[0], entries) - if (insideString) { - continue; - } + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return cb() - if (!insideComment && currentChar + nextChar === '//') { - ret += str.slice(offset, i); - offset = i; - insideComment = singleComment; - i++; - } else if (insideComment === singleComment && currentChar + nextChar === '\r\n') { - i++; - insideComment = false; - ret += strip(str, offset, i); - offset = i; - continue; - } else if (insideComment === singleComment && currentChar === '\n') { - insideComment = false; - ret += strip(str, offset, i); - offset = i; - } else if (!insideComment && currentChar + nextChar === '/*') { - ret += str.slice(offset, i); - offset = i; - insideComment = multiComment; - i++; - continue; - } else if (insideComment === multiComment && currentChar + nextChar === '*/') { - i++; - insideComment = false; - ret += strip(str, offset, i + 1); - offset = i + 1; - continue; - } - } + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [ prefix ] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) - return ret + (insideComment ? strip(str.substr(offset)) : str.substr(offset)); -}; + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false, cb) + var isSym = this.symlinks[abs] + var len = entries.length -/***/ }), -/* 265 */ -/***/ (function(module, exports, __webpack_require__) { + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return cb() -"use strict"; -/*! - * @description Recursive object extending - * @author Viacheslav Lotsmanov - * @license MIT - * - * The MIT License (MIT) - * - * Copyright (c) 2013-2018 Viacheslav Lotsmanov - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true, cb) + var below = gspref.concat(entries[i], remain) + this._process(below, index, true, cb) + } -function isSpecificValue(val) { - return ( - val instanceof Buffer - || val instanceof Date - || val instanceof RegExp - ) ? true : false; + cb() } -function cloneSpecificValue(val) { - if (val instanceof Buffer) { - var x = Buffer.alloc - ? Buffer.alloc(val.length) - : new Buffer(val.length); - val.copy(x); - return x; - } else if (val instanceof Date) { - return new Date(val.getTime()); - } else if (val instanceof RegExp) { - return new RegExp(val); - } else { - throw new Error('Unexpected situation'); - } +Glob.prototype._processSimple = function (prefix, index, cb) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var self = this + this._stat(prefix, function (er, exists) { + self._processSimple2(prefix, index, er, exists, cb) + }) } +Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) { -/** - * Recursive cloning array. - */ -function deepCloneArray(arr) { - var clone = []; - arr.forEach(function (item, index) { - if (typeof item === 'object' && item !== null) { - if (Array.isArray(item)) { - clone[index] = deepCloneArray(item); - } else if (isSpecificValue(item)) { - clone[index] = cloneSpecificValue(item); - } else { - clone[index] = deepExtend({}, item); - } - } else { - clone[index] = item; - } - }); - return clone; -} + //console.error('ps2', prefix, exists) -function safeGetProperty(object, property) { - return property === '__proto__' ? undefined : object[property]; -} + if (!this.matches[index]) + this.matches[index] = Object.create(null) -/** - * Extening object that entered in first argument. - * - * Returns extended object or false if have no target object or incorrect type. - * - * If you wish to clone source object (without modify it), just use empty new - * object as first argument, like this: - * deepExtend({}, yourObj_1, [yourObj_N]); - */ -var deepExtend = module.exports = function (/*obj_1, [obj_2], [obj_N]*/) { - if (arguments.length < 1 || typeof arguments[0] !== 'object') { - return false; - } + // If it doesn't exist, then just mark the lack of results + if (!exists) + return cb() - if (arguments.length < 2) { - return arguments[0]; - } + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } - var target = arguments[0]; + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') - // convert arguments to array and cut off target object - var args = Array.prototype.slice.call(arguments, 1); + // Mark this as a match + this._emitMatch(index, prefix) + cb() +} - var val, src, clone; +// Returns either 'DIR', 'FILE', or false +Glob.prototype._stat = function (f, cb) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' - args.forEach(function (obj) { - // skip argument if isn't an object, is null, or is an array - if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) { - return; - } + if (f.length > this.maxLength) + return cb() - Object.keys(obj).forEach(function (key) { - src = safeGetProperty(target, key); // source value - val = safeGetProperty(obj, key); // new value + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] - // recursion prevention - if (val === target) { - return; + if (Array.isArray(c)) + c = 'DIR' - /** - * if new value isn't object then just overwrite by new value - * instead of extending. - */ - } else if (typeof val !== 'object' || val === null) { - target[key] = val; - return; + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return cb(null, c) - // just clone arrays (and recursive clone objects inside) - } else if (Array.isArray(val)) { - target[key] = deepCloneArray(val); - return; + if (needDir && c === 'FILE') + return cb() - // custom cloning and overwrite for specific objects - } else if (isSpecificValue(val)) { - target[key] = cloneSpecificValue(val); - return; + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } - // overwrite by new value if source isn't object or array - } else if (typeof src !== 'object' || src === null || Array.isArray(src)) { - target[key] = deepExtend({}, val); - return; + var exists + var stat = this.statCache[abs] + if (stat !== undefined) { + if (stat === false) + return cb(null, stat) + else { + var type = stat.isDirectory() ? 'DIR' : 'FILE' + if (needDir && type === 'FILE') + return cb() + else + return cb(null, type, stat) + } + } - // source value and new value is objects both, extending... - } else { - target[key] = deepExtend(src, val); - return; - } - }); - }); + var self = this + var statcb = inflight('stat\0' + abs, lstatcb_) + if (statcb) + fs.lstat(abs, statcb) - return target; -}; + function lstatcb_ (er, lstat) { + if (lstat && lstat.isSymbolicLink()) { + // If it's a symlink, then treat it as the target, unless + // the target does not exist, then treat it as a file. + return fs.stat(abs, function (er, stat) { + if (er) + self._stat2(f, abs, null, lstat, cb) + else + self._stat2(f, abs, er, stat, cb) + }) + } else { + self._stat2(f, abs, er, lstat, cb) + } + } +} +Glob.prototype._stat2 = function (f, abs, er, stat, cb) { + if (er) { + this.statCache[abs] = false + return cb() + } -/***/ }), -/* 266 */ -/***/ (function(module, exports) { + var needDir = f.slice(-1) === '/' + this.statCache[abs] = stat -module.exports = function (args, opts) { - if (!opts) opts = {}; - - var flags = { bools : {}, strings : {}, unknownFn: null }; + if (abs.slice(-1) === '/' && !stat.isDirectory()) + return cb(null, false, stat) - if (typeof opts['unknown'] === 'function') { - flags.unknownFn = opts['unknown']; - } + var c = stat.isDirectory() ? 'DIR' : 'FILE' + this.cache[abs] = this.cache[abs] || c - if (typeof opts['boolean'] === 'boolean' && opts['boolean']) { - flags.allBools = true; - } else { - [].concat(opts['boolean']).filter(Boolean).forEach(function (key) { - flags.bools[key] = true; - }); - } - - var aliases = {}; - Object.keys(opts.alias || {}).forEach(function (key) { - aliases[key] = [].concat(opts.alias[key]); - aliases[key].forEach(function (x) { - aliases[x] = [key].concat(aliases[key].filter(function (y) { - return x !== y; - })); - }); - }); + if (needDir && c !== 'DIR') + return cb() - [].concat(opts.string).filter(Boolean).forEach(function (key) { - flags.strings[key] = true; - if (aliases[key]) { - flags.strings[aliases[key]] = true; - } - }); + return cb(null, c, stat) +} - var defaults = opts['default'] || {}; - - var argv = { _ : [] }; - Object.keys(flags.bools).forEach(function (key) { - setArg(key, defaults[key] === undefined ? false : defaults[key]); - }); - - var notFlags = []; - if (args.indexOf('--') !== -1) { - notFlags = args.slice(args.indexOf('--')+1); - args = args.slice(0, args.indexOf('--')); - } +/***/ }), +/* 261 */ +/***/ (function(module, exports, __webpack_require__) { - function argDefined(key, arg) { - return (flags.allBools && /^--[^=]+$/.test(arg)) || - flags.strings[key] || flags.bools[key] || aliases[key]; - } +module.exports = globSync +globSync.GlobSync = GlobSync - function setArg (key, val, arg) { - if (arg && flags.unknownFn && !argDefined(key, arg)) { - if (flags.unknownFn(arg) === false) return; - } +var fs = __webpack_require__(4) +var minimatch = __webpack_require__(204) +var Minimatch = minimatch.Minimatch +var Glob = __webpack_require__(260).Glob +var util = __webpack_require__(12) +var path = __webpack_require__(20) +var assert = __webpack_require__(46) +var isAbsolute = __webpack_require__(240) +var common = __webpack_require__(262) +var alphasort = common.alphasort +var alphasorti = common.alphasorti +var setopts = common.setopts +var ownProp = common.ownProp +var childrenIgnored = common.childrenIgnored - var value = !flags.strings[key] && isNumber(val) - ? Number(val) : val - ; - setKey(argv, key.split('.'), value); - - (aliases[key] || []).forEach(function (x) { - setKey(argv, x.split('.'), value); - }); - } +function globSync (pattern, options) { + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n'+ + 'See: https://github.com/isaacs/node-glob/issues/167') - function setKey (obj, keys, value) { - var o = obj; - keys.slice(0,-1).forEach(function (key) { - if (o[key] === undefined) o[key] = {}; - o = o[key]; - }); + return new GlobSync(pattern, options).found +} - var key = keys[keys.length - 1]; - if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') { - o[key] = value; - } - else if (Array.isArray(o[key])) { - o[key].push(value); - } - else { - o[key] = [ o[key], value ]; - } - } - - function aliasIsBoolean(key) { - return aliases[key].some(function (x) { - return flags.bools[x]; - }); - } +function GlobSync (pattern, options) { + if (!pattern) + throw new Error('must provide pattern') - for (var i = 0; i < args.length; i++) { - var arg = args[i]; - - if (/^--.+=/.test(arg)) { - // Using [\s\S] instead of . because js doesn't support the - // 'dotall' regex modifier. See: - // http://stackoverflow.com/a/1068308/13216 - var m = arg.match(/^--([^=]+)=([\s\S]*)$/); - var key = m[1]; - var value = m[2]; - if (flags.bools[key]) { - value = value !== 'false'; - } - setArg(key, value, arg); - } - else if (/^--no-.+/.test(arg)) { - var key = arg.match(/^--no-(.+)/)[1]; - setArg(key, false, arg); - } - else if (/^--.+/.test(arg)) { - var key = arg.match(/^--(.+)/)[1]; - var next = args[i + 1]; - if (next !== undefined && !/^-/.test(next) - && !flags.bools[key] - && !flags.allBools - && (aliases[key] ? !aliasIsBoolean(key) : true)) { - setArg(key, next, arg); - i++; - } - else if (/^(true|false)$/.test(next)) { - setArg(key, next === 'true', arg); - i++; - } - else { - setArg(key, flags.strings[key] ? '' : true, arg); - } - } - else if (/^-[^-]+/.test(arg)) { - var letters = arg.slice(1,-1).split(''); - - var broken = false; - for (var j = 0; j < letters.length; j++) { - var next = arg.slice(j+2); - - if (next === '-') { - setArg(letters[j], next, arg) - continue; - } - - if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) { - setArg(letters[j], next.split('=')[1], arg); - broken = true; - break; - } - - if (/[A-Za-z]/.test(letters[j]) - && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { - setArg(letters[j], next, arg); - broken = true; - break; - } - - if (letters[j+1] && letters[j+1].match(/\W/)) { - setArg(letters[j], arg.slice(j+2), arg); - broken = true; - break; - } - else { - setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg); - } - } - - var key = arg.slice(-1)[0]; - if (!broken && key !== '-') { - if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1]) - && !flags.bools[key] - && (aliases[key] ? !aliasIsBoolean(key) : true)) { - setArg(key, args[i+1], arg); - i++; - } - else if (args[i+1] && /true|false/.test(args[i+1])) { - setArg(key, args[i+1] === 'true', arg); - i++; - } - else { - setArg(key, flags.strings[key] ? '' : true, arg); - } - } - } - else { - if (!flags.unknownFn || flags.unknownFn(arg) !== false) { - argv._.push( - flags.strings['_'] || !isNumber(arg) ? arg : Number(arg) - ); - } - if (opts.stopEarly) { - argv._.push.apply(argv._, args.slice(i + 1)); - break; - } - } - } - - Object.keys(defaults).forEach(function (key) { - if (!hasKey(argv, key.split('.'))) { - setKey(argv, key.split('.'), defaults[key]); - - (aliases[key] || []).forEach(function (x) { - setKey(argv, x.split('.'), defaults[key]); - }); - } - }); - - if (opts['--']) { - argv['--'] = new Array(); - notFlags.forEach(function(key) { - argv['--'].push(key); - }); - } - else { - notFlags.forEach(function(key) { - argv._.push(key); - }); - } + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n'+ + 'See: https://github.com/isaacs/node-glob/issues/167') - return argv; -}; + if (!(this instanceof GlobSync)) + return new GlobSync(pattern, options) -function hasKey (obj, keys) { - var o = obj; - keys.slice(0,-1).forEach(function (key) { - o = (o[key] || {}); - }); + setopts(this, pattern, options) - var key = keys[keys.length - 1]; - return key in o; + if (this.noprocess) + return this + + var n = this.minimatch.set.length + this.matches = new Array(n) + for (var i = 0; i < n; i ++) { + this._process(this.minimatch.set[i], i, false) + } + this._finish() } -function isNumber (x) { - if (typeof x === 'number') return true; - if (/^0x[0-9a-f]+$/i.test(x)) return true; - return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x); +GlobSync.prototype._finish = function () { + assert(this instanceof GlobSync) + if (this.realpath) { + var self = this + this.matches.forEach(function (matchset, index) { + var set = self.matches[index] = Object.create(null) + for (var p in matchset) { + try { + p = self._makeAbs(p) + var real = fs.realpathSync(p, self.realpathCache) + set[real] = true + } catch (er) { + if (er.syscall === 'stat') + set[self._makeAbs(p)] = true + else + throw er + } + } + }) + } + common.finish(this) } +GlobSync.prototype._process = function (pattern, index, inGlobStar) { + assert(this instanceof GlobSync) -/***/ }), -/* 267 */ -/***/ (function(module, exports) { + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n ++ + } + // now n is the index of the first one that is *not* a string. -module.exports = require("url"); + // See if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index) + return -/***/ }), -/* 268 */ -/***/ (function(module, exports, __webpack_require__) { + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break -"use strict"; + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } -Object.defineProperty(exports, "__esModule", { value: true }); -const tslib_1 = __webpack_require__(3); -const follow_redirects_1 = __webpack_require__(269); -const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); -const mkdirp_1 = tslib_1.__importDefault(__webpack_require__(182)); -const path_1 = tslib_1.__importDefault(__webpack_require__(20)); -const tar_1 = tslib_1.__importDefault(__webpack_require__(276)); -const url_1 = __webpack_require__(267); -const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const fetch_1 = __webpack_require__(307); -/** - * Download and extract tgz from url - * - * @param {string} url - * @param {DownloadOptions} options contains dest folder and optional onProgress callback - */ -function download(url, options) { - const rejectUnauthorized = workspace_1.default.getConfiguration('https').get('rejectUnauthorized', true); - let { dest, onProgress } = options; - if (!dest || !path_1.default.isAbsolute(dest)) { - throw new Error(`Expect absolute file path for dest option.`); - } - if (!fs_1.default.existsSync(dest)) - mkdirp_1.default.sync(dest); - let endpoint = url_1.parse(url); - let mod = url.startsWith('https') ? follow_redirects_1.https : follow_redirects_1.http; - let agent = fetch_1.getAgent(endpoint); - let opts = Object.assign({ - method: 'GET', - hostname: endpoint.hostname, - port: endpoint.port ? parseInt(endpoint.port, 10) : (endpoint.protocol === 'https:' ? 443 : 80), - path: endpoint.path, - protocol: url.startsWith('https') ? 'https:' : 'http:', - agent, - rejectUnauthorized, - headers: { - 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64)' - } - }, options); - return new Promise((resolve, reject) => { - const req = mod.request(opts, (res) => { - if (res.statusCode != 200) { - reject(new Error(`Invalid response from ${url}: ${res.statusCode}`)); - return; - } - if (onProgress) { - const len = parseInt(res.headers['content-length'], 10); - let cur = 0; - if (!isNaN(len)) { - res.on('data', chunk => { - cur += chunk.length; - onProgress(cur / len); - }); - } - } - let stream = res.pipe(tar_1.default.x({ strip: 1, C: dest })); - stream.on('finish', () => { - setTimeout(resolve, 100); - }); - stream.on('error', reject); - }); - req.on('error', reject); - req.end(); - }); -} -exports.default = download; -//# sourceMappingURL=download.js.map + var remain = pattern.slice(n) -/***/ }), -/* 269 */ -/***/ (function(module, exports, __webpack_require__) { + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix -var url = __webpack_require__(267); -var URL = url.URL; -var http = __webpack_require__(270); -var https = __webpack_require__(271); -var assert = __webpack_require__(46); -var Writable = __webpack_require__(44).Writable; -var debug = __webpack_require__(272)("follow-redirects"); + var abs = this._makeAbs(read) -// RFC7231§4.2.1: Of the request methods defined by this specification, -// the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe. -var SAFE_METHODS = { GET: true, HEAD: true, OPTIONS: true, TRACE: true }; + //if ignored, skip processing + if (childrenIgnored(this, read)) + return -// Create handlers that pass events from native requests -var eventHandlers = Object.create(null); -["abort", "aborted", "connect", "error", "socket", "timeout"].forEach(function (event) { - eventHandlers[event] = function (arg1, arg2, arg3) { - this._redirectable.emit(event, arg1, arg2, arg3); - }; -}); + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar) +} -// An HTTP(S) request that can be redirected -function RedirectableRequest(options, responseCallback) { - // Initialize the request - Writable.call(this); - this._sanitizeOptions(options); - this._options = options; - this._ended = false; - this._ending = false; - this._redirectCount = 0; - this._redirects = []; - this._requestBodyLength = 0; - this._requestBodyBuffers = []; - // Attach a callback if passed - if (responseCallback) { - this.on("response", responseCallback); - } +GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) { + var entries = this._readdir(abs, inGlobStar) - // React to responses of native requests - var self = this; - this._onNativeResponse = function (response) { - self._processResponse(response); - }; + // if the abs isn't a dir, then nothing can match! + if (!entries) + return - // Perform the first request - this._performRequest(); -} -RedirectableRequest.prototype = Object.create(Writable.prototype); + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' -// Writes buffered data to the current native request -RedirectableRequest.prototype.write = function (data, encoding, callback) { - // Writing is not allowed if end has been called - if (this._ending) { - throw new Error("write after end"); + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) + } } - // Validate input and shift parameters if necessary - if (!(typeof data === "string" || typeof data === "object" && ("length" in data))) { - throw new Error("data should be a string, Buffer or Uint8Array"); - } - if (typeof encoding === "function") { - callback = encoding; - encoding = null; - } + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return - // Ignore empty buffers, since writing them doesn't invoke the callback - // https://github.com/nodejs/node/issues/22066 - if (data.length === 0) { - if (callback) { - callback(); - } - return; - } - // Only write when we don't exceed the maximum body length - if (this._requestBodyLength + data.length <= this._options.maxBodyLength) { - this._requestBodyLength += data.length; - this._requestBodyBuffers.push({ data: data, encoding: encoding }); - this._currentRequest.write(data, encoding, callback); - } - // Error when we exceed the maximum body length - else { - this.emit("error", new Error("Request body larger than maxBodyLength limit")); - this.abort(); - } -}; + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. -// Ends the current native request -RedirectableRequest.prototype.end = function (data, encoding, callback) { - // Shift parameters if necessary - if (typeof data === "function") { - callback = data; - data = encoding = null; - } - else if (typeof encoding === "function") { - callback = encoding; - encoding = null; - } + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) - // Write data if needed and end - if (!data) { - this._ended = this._ending = true; - this._currentRequest.end(null, null, callback); - } - else { - var self = this; - var currentRequest = this._currentRequest; - this.write(data, encoding, function () { - self._ended = true; - currentRequest.end(null, null, callback); - }); - this._ending = true; - } -}; - -// Sets a header value on the current native request -RedirectableRequest.prototype.setHeader = function (name, value) { - this._options.headers[name] = value; - this._currentRequest.setHeader(name, value); -}; - -// Clears a header value on the current native request -RedirectableRequest.prototype.removeHeader = function (name) { - delete this._options.headers[name]; - this._currentRequest.removeHeader(name); -}; + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix.slice(-1) !== '/') + e = prefix + '/' + e + else + e = prefix + e + } -// Global timeout for all underlying requests -RedirectableRequest.prototype.setTimeout = function (msecs, callback) { - if (callback) { - this.once("timeout", callback); + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this.matches[index][e] = true + } + // This was the last one, and no stats were needed + return } - if (this.socket) { - startTimer(this, msecs); - } - else { - var self = this; - this._currentRequest.once("socket", function () { - startTimer(self, msecs); - }); + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + var newPattern + if (prefix) + newPattern = [prefix, e] + else + newPattern = [e] + this._process(newPattern.concat(remain), index, inGlobStar) } +} - this.once("response", clearTimer); - this.once("error", clearTimer); - return this; -}; +GlobSync.prototype._emitMatch = function (index, e) { + var abs = this._makeAbs(e) + if (this.mark) + e = this._mark(e) -function startTimer(request, msecs) { - clearTimeout(request._timeout); - request._timeout = setTimeout(function () { - request.emit("timeout"); - }, msecs); -} + if (this.matches[index][e]) + return -function clearTimer() { - clearTimeout(this._timeout); + if (this.nodir) { + var c = this.cache[this._makeAbs(e)] + if (c === 'DIR' || Array.isArray(c)) + return + } + + this.matches[index][e] = true + if (this.stat) + this._stat(e) } -// Proxy all other public ClientRequest methods -[ - "abort", "flushHeaders", "getHeader", - "setNoDelay", "setSocketKeepAlive", -].forEach(function (method) { - RedirectableRequest.prototype[method] = function (a, b) { - return this._currentRequest[method](a, b); - }; -}); -// Proxy all public ClientRequest properties -["aborted", "connection", "socket"].forEach(function (property) { - Object.defineProperty(RedirectableRequest.prototype, property, { - get: function () { return this._currentRequest[property]; }, - }); -}); +GlobSync.prototype._readdirInGlobStar = function (abs) { + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false) -RedirectableRequest.prototype._sanitizeOptions = function (options) { - // Ensure headers are always present - if (!options.headers) { - options.headers = {}; + var entries + var lstat + var stat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + // lstat failed, doesn't exist + return null } - // Since http.request treats host as an alias of hostname, - // but the url module interprets host as hostname plus port, - // eliminate the host property to avoid confusion. - if (options.host) { - // Use hostname if set, because it has precedence - if (!options.hostname) { - options.hostname = options.host; - } - delete options.host; - } + var isSym = lstat.isSymbolicLink() + this.symlinks[abs] = isSym - // Complete the URL object when necessary - if (!options.pathname && options.path) { - var searchPos = options.path.indexOf("?"); - if (searchPos < 0) { - options.pathname = options.path; - } - else { - options.pathname = options.path.substring(0, searchPos); - options.search = options.path.substring(searchPos); - } - } -}; + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && !lstat.isDirectory()) + this.cache[abs] = 'FILE' + else + entries = this._readdir(abs, false) + return entries +} -// Executes the next native request (initial or redirect) -RedirectableRequest.prototype._performRequest = function () { - // Load the native protocol - var protocol = this._options.protocol; - var nativeProtocol = this._options.nativeProtocols[protocol]; - if (!nativeProtocol) { - this.emit("error", new Error("Unsupported protocol " + protocol)); - return; - } +GlobSync.prototype._readdir = function (abs, inGlobStar) { + var entries - // If specified, use the agent corresponding to the protocol - // (HTTP and HTTPS use different types of agents) - if (this._options.agents) { - var scheme = protocol.substr(0, protocol.length - 1); - this._options.agent = this._options.agents[scheme]; - } + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs) - // Create the native request - var request = this._currentRequest = - nativeProtocol.request(this._options, this._onNativeResponse); - this._currentUrl = url.format(this._options); + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return null - // Set up event handlers - request._redirectable = this; - for (var event in eventHandlers) { - /* istanbul ignore else */ - if (event) { - request.on(event, eventHandlers[event]); - } + if (Array.isArray(c)) + return c } - // End a redirected request - // (The first request must be ended explicitly with RedirectableRequest#end) - if (this._isRedirect) { - // Write the request entity and end. - var i = 0; - var self = this; - var buffers = this._requestBodyBuffers; - (function writeNext(error) { - // Only write if this request has not been redirected yet - /* istanbul ignore else */ - if (request === self._currentRequest) { - // Report any write errors - /* istanbul ignore if */ - if (error) { - self.emit("error", error); - } - // Write the next buffer if there are still left - else if (i < buffers.length) { - var buffer = buffers[i++]; - /* istanbul ignore else */ - if (!request.finished) { - request.write(buffer.data, buffer.encoding, writeNext); - } - } - // End the request if `end` has been called on us - else if (self._ended) { - request.end(); - } - } - }()); + try { + return this._readdirEntries(abs, fs.readdirSync(abs)) + } catch (er) { + this._readdirError(abs, er) + return null } -}; +} -// Processes a response from the current native request -RedirectableRequest.prototype._processResponse = function (response) { - // Store the redirected response - var statusCode = response.statusCode; - if (this._options.trackRedirects) { - this._redirects.push({ - url: this._currentUrl, - headers: response.headers, - statusCode: statusCode, - }); +GlobSync.prototype._readdirEntries = function (abs, entries) { + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i ++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } } - // RFC7231§6.4: The 3xx (Redirection) class of status code indicates - // that further action needs to be taken by the user agent in order to - // fulfill the request. If a Location header field is provided, - // the user agent MAY automatically redirect its request to the URI - // referenced by the Location field value, - // even if the specific status code is not understood. - var location = response.headers.location; - if (location && this._options.followRedirects !== false && - statusCode >= 300 && statusCode < 400) { - // Abort the current request - this._currentRequest.removeAllListeners(); - this._currentRequest.on("error", noop); - this._currentRequest.abort(); - // Discard the remainder of the response to avoid waiting for data - response.destroy(); + this.cache[abs] = entries - // RFC7231§6.4: A client SHOULD detect and intervene - // in cyclical redirections (i.e., "infinite" redirection loops). - if (++this._redirectCount > this._options.maxRedirects) { - this.emit("error", new Error("Max redirects exceeded.")); - return; - } + // mark and cache dir-ness + return entries +} - // RFC7231§6.4: Automatic redirection needs to done with - // care for methods not known to be safe […], - // since the user might not wish to redirect an unsafe request. - // RFC7231§6.4.7: The 307 (Temporary Redirect) status code indicates - // that the target resource resides temporarily under a different URI - // and the user agent MUST NOT change the request method - // if it performs an automatic redirection to that URI. - var header; - var headers = this._options.headers; - if (statusCode !== 307 && !(this._options.method in SAFE_METHODS)) { - this._options.method = "GET"; - // Drop a possible entity and headers related to it - this._requestBodyBuffers = []; - for (header in headers) { - if (/^content-/i.test(header)) { - delete headers[header]; - } - } - } +GlobSync.prototype._readdirError = function (f, er) { + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + this.cache[this._makeAbs(f)] = 'FILE' + break - // Drop the Host header, as the redirect might lead to a different host - if (!this._isRedirect) { - for (header in headers) { - if (/^host$/i.test(header)) { - delete headers[header]; - } - } - } + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break - // Perform the redirected request - var redirectUrl = url.resolve(this._currentUrl, location); - debug("redirecting to", redirectUrl); - Object.assign(this._options, url.parse(redirectUrl)); - if (typeof this._options.beforeRedirect === "function") { - try { - this._options.beforeRedirect.call(null, this._options); - } - catch (err) { - this.emit("error", err); - return; - } - this._sanitizeOptions(this._options); - } - this._isRedirect = true; - this._performRequest(); + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) + throw er + if (!this.silent) + console.error('glob error', er) + break } - else { - // The response is not a redirect; return it as-is - response.responseUrl = this._currentUrl; - response.redirects = this._redirects; - this.emit("response", response); +} - // Clean up - this._requestBodyBuffers = []; - } -}; +GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) { -// Wraps the key/value object of protocols with redirect functionality -function wrap(protocols) { - // Default settings - var exports = { - maxRedirects: 21, - maxBodyLength: 10 * 1024 * 1024, - }; + var entries = this._readdir(abs, inGlobStar) - // Wrap each protocol - var nativeProtocols = {}; - Object.keys(protocols).forEach(function (scheme) { - var protocol = scheme + ":"; - var nativeProtocol = nativeProtocols[protocol] = protocols[scheme]; - var wrappedProtocol = exports[scheme] = Object.create(nativeProtocol); + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return - // Executes a request, following redirects - wrappedProtocol.request = function (input, options, callback) { - // Parse parameters - if (typeof input === "string") { - var urlStr = input; - try { - input = urlToOptions(new URL(urlStr)); - } - catch (err) { - /* istanbul ignore next */ - input = url.parse(urlStr); - } - } - else if (URL && (input instanceof URL)) { - input = urlToOptions(input); - } - else { - callback = options; - options = input; - input = { protocol: protocol }; - } - if (typeof options === "function") { - callback = options; - options = null; - } + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [ prefix ] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) - // Set defaults - options = Object.assign({ - maxRedirects: exports.maxRedirects, - maxBodyLength: exports.maxBodyLength, - }, input, options); - options.nativeProtocols = nativeProtocols; + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false) - assert.equal(options.protocol, protocol, "protocol mismatch"); - debug("options", options); - return new RedirectableRequest(options, callback); - }; + var len = entries.length + var isSym = this.symlinks[abs] - // Executes a GET request, following redirects - wrappedProtocol.get = function (input, options, callback) { - var request = wrappedProtocol.request(input, options, callback); - request.end(); - return request; - }; - }); - return exports; -} + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return -/* istanbul ignore next */ -function noop() { /* empty */ } + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue -// from https://github.com/nodejs/node/blob/master/lib/internal/url.js -function urlToOptions(urlObject) { - var options = { - protocol: urlObject.protocol, - hostname: urlObject.hostname.startsWith("[") ? - /* istanbul ignore next */ - urlObject.hostname.slice(1, -1) : - urlObject.hostname, - hash: urlObject.hash, - search: urlObject.search, - pathname: urlObject.pathname, - path: urlObject.pathname + urlObject.search, - href: urlObject.href, - }; - if (urlObject.port !== "") { - options.port = Number(urlObject.port); + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true) + + var below = gspref.concat(entries[i], remain) + this._process(below, index, true) } - return options; } -// Exports -module.exports = wrap({ http: http, https: https }); -module.exports.wrap = wrap; +GlobSync.prototype._processSimple = function (prefix, index) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var exists = this._stat(prefix) + if (!this.matches[index]) + this.matches[index] = Object.create(null) -/***/ }), -/* 270 */ -/***/ (function(module, exports) { + // If it doesn't exist, then just mark the lack of results + if (!exists) + return -module.exports = require("http"); + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } -/***/ }), -/* 271 */ -/***/ (function(module, exports) { + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') -module.exports = require("https"); + // Mark this as a match + this.matches[index][prefix] = true +} -/***/ }), -/* 272 */ -/***/ (function(module, exports, __webpack_require__) { +// Returns either 'DIR', 'FILE', or false +GlobSync.prototype._stat = function (f) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' -"use strict"; + if (f.length > this.maxLength) + return false + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] -/** - * Detect Electron renderer / nwjs process, which is node, but we should - * treat as a browser. - */ -if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { - module.exports = __webpack_require__(273); -} else { - module.exports = __webpack_require__(275); -} + if (Array.isArray(c)) + c = 'DIR' + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return c + if (needDir && c === 'FILE') + return false -/***/ }), -/* 273 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } -/* eslint-env browser */ + var exists + var stat = this.statCache[abs] + if (!stat) { + var lstat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + return false + } -/** - * This is the web browser implementation of `debug()`. - */ -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.storage = localstorage(); -/** - * Colors. - */ + if (lstat.isSymbolicLink()) { + try { + stat = fs.statSync(abs) + } catch (er) { + stat = lstat + } + } else { + stat = lstat + } + } -exports.colors = ['#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33']; -/** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ -// eslint-disable-next-line complexity + this.statCache[abs] = stat -function useColors() { - // NB: In an Electron preload script, document will be defined but not fully - // initialized. Since we know we're in Chrome, we'll just detect this case - // explicitly - if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { - return true; - } // Internet Explorer and Edge do not support colors. + var c = stat.isDirectory() ? 'DIR' : 'FILE' + this.cache[abs] = this.cache[abs] || c + if (needDir && c !== 'DIR') + return false - if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { - return false; - } // Is webkit? http://stackoverflow.com/a/16459606/376773 - // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return c +} +GlobSync.prototype._mark = function (p) { + return common.mark(this, p) +} - return typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773 - typeof window !== 'undefined' && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker - typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/); +GlobSync.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) } -/** - * Colorize log arguments if enabled. - * - * @api public - */ -function formatArgs(args) { - args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + '+' + module.exports.humanize(this.diff); +/***/ }), +/* 262 */ +/***/ (function(module, exports, __webpack_require__) { - if (!this.useColors) { - return; - } +exports.alphasort = alphasort +exports.alphasorti = alphasorti +exports.setopts = setopts +exports.ownProp = ownProp +exports.makeAbs = makeAbs +exports.finish = finish +exports.mark = mark +exports.isIgnored = isIgnored +exports.childrenIgnored = childrenIgnored - var c = 'color: ' + this.color; - args.splice(1, 0, c, 'color: inherit'); // The final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into +function ownProp (obj, field) { + return Object.prototype.hasOwnProperty.call(obj, field) +} - var index = 0; - var lastC = 0; - args[0].replace(/%[a-zA-Z%]/g, function (match) { - if (match === '%%') { - return; - } +var path = __webpack_require__(20) +var minimatch = __webpack_require__(204) +var isAbsolute = __webpack_require__(240) +var Minimatch = minimatch.Minimatch - index++; +function alphasorti (a, b) { + return a.toLowerCase().localeCompare(b.toLowerCase()) +} - if (match === '%c') { - // We only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); - args.splice(lastC, 0, c); +function alphasort (a, b) { + return a.localeCompare(b) } -/** - * Invokes `console.log()` when available. - * No-op when `console.log` is not a "function". - * - * @api public - */ +function setupIgnores (self, options) { + self.ignore = options.ignore || [] -function log() { - var _console; + if (!Array.isArray(self.ignore)) + self.ignore = [self.ignore] - // This hackery is required for IE8/9, where - // the `console.log` function doesn't have 'apply' - return (typeof console === "undefined" ? "undefined" : _typeof(console)) === 'object' && console.log && (_console = console).log.apply(_console, arguments); + if (self.ignore.length) { + self.ignore = self.ignore.map(ignoreMap) + } } -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ +// ignore patterns are always in dot:true mode. +function ignoreMap (pattern) { + var gmatcher = null + if (pattern.slice(-3) === '/**') { + var gpattern = pattern.replace(/(\/\*\*)+$/, '') + gmatcher = new Minimatch(gpattern, { dot: true }) + } -function save(namespaces) { - try { - if (namespaces) { - exports.storage.setItem('debug', namespaces); - } else { - exports.storage.removeItem('debug'); - } - } catch (error) {// Swallow - // XXX (@Qix-) should we be logging these? + return { + matcher: new Minimatch(pattern, { dot: true }), + gmatcher: gmatcher } } -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ +function setopts (self, pattern, options) { + if (!options) + options = {} -function load() { - var r; + // base-matching: just use globstar for that. + if (options.matchBase && -1 === pattern.indexOf("/")) { + if (options.noglobstar) { + throw new Error("base matching requires globstar") + } + pattern = "**/" + pattern + } - try { - r = exports.storage.getItem('debug'); - } catch (error) {} // Swallow - // XXX (@Qix-) should we be logging these? - // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + self.silent = !!options.silent + self.pattern = pattern + self.strict = options.strict !== false + self.realpath = !!options.realpath + self.realpathCache = options.realpathCache || Object.create(null) + self.follow = !!options.follow + self.dot = !!options.dot + self.mark = !!options.mark + self.nodir = !!options.nodir + if (self.nodir) + self.mark = true + self.sync = !!options.sync + self.nounique = !!options.nounique + self.nonull = !!options.nonull + self.nosort = !!options.nosort + self.nocase = !!options.nocase + self.stat = !!options.stat + self.noprocess = !!options.noprocess + + self.maxLength = options.maxLength || Infinity + self.cache = options.cache || Object.create(null) + self.statCache = options.statCache || Object.create(null) + self.symlinks = options.symlinks || Object.create(null) + setupIgnores(self, options) - if (!r && typeof process !== 'undefined' && 'env' in process) { - r = process.env.DEBUG; + self.changedCwd = false + var cwd = process.cwd() + if (!ownProp(options, "cwd")) + self.cwd = cwd + else { + self.cwd = options.cwd + self.changedCwd = path.resolve(options.cwd) !== cwd } - return r; -} -/** - * Localstorage attempts to return the localstorage. - * - * This is necessary because safari throws - * when a user disables cookies/localstorage - * and you attempt to access it. - * - * @return {LocalStorage} - * @api private - */ + self.root = options.root || path.resolve(self.cwd, "/") + self.root = path.resolve(self.root) + if (process.platform === "win32") + self.root = self.root.replace(/\\/g, "/") + self.nomount = !!options.nomount -function localstorage() { - try { - // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context - // The Browser also has localStorage in the global context. - return localStorage; - } catch (error) {// Swallow - // XXX (@Qix-) should we be logging these? - } + // disable comments and negation in Minimatch. + // Note that they are not supported in Glob itself anyway. + options.nonegate = true + options.nocomment = true + + self.minimatch = new Minimatch(pattern, options) + self.options = self.minimatch.options } -module.exports = __webpack_require__(274)(exports); -var formatters = module.exports.formatters; -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ +function finish (self) { + var nou = self.nounique + var all = nou ? [] : Object.create(null) -formatters.j = function (v) { - try { - return JSON.stringify(v); - } catch (error) { - return '[UnexpectedJSONParseError]: ' + error.message; + for (var i = 0, l = self.matches.length; i < l; i ++) { + var matches = self.matches[i] + if (!matches || Object.keys(matches).length === 0) { + if (self.nonull) { + // do like the shell, and spit out the literal glob + var literal = self.minimatch.globSet[i] + if (nou) + all.push(literal) + else + all[literal] = true + } + } else { + // had matches + var m = Object.keys(matches) + if (nou) + all.push.apply(all, m) + else + m.forEach(function (m) { + all[m] = true + }) + } } -}; - - -/***/ }), -/* 274 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; + if (!nou) + all = Object.keys(all) + if (!self.nosort) + all = all.sort(self.nocase ? alphasorti : alphasort) -/** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - */ -function setup(env) { - createDebug.debug = createDebug; - createDebug.default = createDebug; - createDebug.coerce = coerce; - createDebug.disable = disable; - createDebug.enable = enable; - createDebug.enabled = enabled; - createDebug.humanize = __webpack_require__(9); - Object.keys(env).forEach(function (key) { - createDebug[key] = env[key]; - }); - /** - * Active `debug` instances. - */ + // at *some* point we statted all of these + if (self.mark) { + for (var i = 0; i < all.length; i++) { + all[i] = self._mark(all[i]) + } + if (self.nodir) { + all = all.filter(function (e) { + return !(/\/$/.test(e)) + }) + } + } - createDebug.instances = []; - /** - * The currently active debug mode names, and names to skip. - */ + if (self.ignore.length) + all = all.filter(function(m) { + return !isIgnored(self, m) + }) - createDebug.names = []; - createDebug.skips = []; - /** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". - */ + self.found = all +} - createDebug.formatters = {}; - /** - * Selects a color for a debug namespace - * @param {String} namespace The namespace string for the for the debug instance to be colored - * @return {Number|String} An ANSI color code for the given namespace - * @api private - */ +function mark (self, p) { + var abs = makeAbs(self, p) + var c = self.cache[abs] + var m = p + if (c) { + var isDir = c === 'DIR' || Array.isArray(c) + var slash = p.slice(-1) === '/' - function selectColor(namespace) { - var hash = 0; + if (isDir && !slash) + m += '/' + else if (!isDir && slash) + m = m.slice(0, -1) - for (var i = 0; i < namespace.length; i++) { - hash = (hash << 5) - hash + namespace.charCodeAt(i); - hash |= 0; // Convert to 32bit integer + if (m !== p) { + var mabs = makeAbs(self, m) + self.statCache[mabs] = self.statCache[abs] + self.cache[mabs] = self.cache[abs] } - - return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; } - createDebug.selectColor = selectColor; - /** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - - function createDebug(namespace) { - var prevTime; - - function debug() { - // Disabled? - if (!debug.enabled) { - return; - } + return m +} - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } +// lotta situps... +function makeAbs (self, f) { + var abs = f + if (f.charAt(0) === '/') { + abs = path.join(self.root, f) + } else if (isAbsolute(f) || f === '') { + abs = f + } else if (self.changedCwd) { + abs = path.resolve(self.cwd, f) + } else { + abs = path.resolve(f) + } + return abs +} - var self = debug; // Set `diff` timestamp - var curr = Number(new Date()); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - args[0] = createDebug.coerce(args[0]); +// Return true, if pattern ends with globstar '**', for the accompanying parent directory. +// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents +function isIgnored (self, path) { + if (!self.ignore.length) + return false - if (typeof args[0] !== 'string') { - // Anything else let's inspect with %O - args.unshift('%O'); - } // Apply any `formatters` transformations + return self.ignore.some(function(item) { + return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path)) + }) +} +function childrenIgnored (self, path) { + if (!self.ignore.length) + return false - var index = 0; - args[0] = args[0].replace(/%([a-zA-Z%])/g, function (match, format) { - // If we encounter an escaped % then don't increase the array index - if (match === '%%') { - return match; - } + return self.ignore.some(function(item) { + return !!(item.gmatcher && item.gmatcher.match(path)) + }) +} - index++; - var formatter = createDebug.formatters[format]; - if (typeof formatter === 'function') { - var val = args[index]; - match = formatter.call(self, val); // Now we need to remove `args[index]` since it's inlined in the `format` +/***/ }), +/* 263 */ +/***/ (function(module, exports, __webpack_require__) { - args.splice(index, 1); - index--; - } +var cc = __webpack_require__(264) +var join = __webpack_require__(20).join +var deepExtend = __webpack_require__(267) +var etc = '/etc' +var win = process.platform === "win32" +var home = win + ? process.env.USERPROFILE + : process.env.HOME - return match; - }); // Apply env-specific formatting (colors, etc.) +module.exports = function (name, defaults, argv, parse) { + if('string' !== typeof name) + throw new Error('rc(name): name *must* be string') + if(!argv) + argv = __webpack_require__(268)(process.argv.slice(2)) + defaults = ( + 'string' === typeof defaults + ? cc.json(defaults) : defaults + ) || {} - createDebug.formatArgs.call(self, args); - var logFn = self.log || createDebug.log; - logFn.apply(self, args); - } + parse = parse || cc.parse - debug.namespace = namespace; - debug.enabled = createDebug.enabled(namespace); - debug.useColors = createDebug.useColors(); - debug.color = selectColor(namespace); - debug.destroy = destroy; - debug.extend = extend; // Debug.formatArgs = formatArgs; - // debug.rawLog = rawLog; - // env-specific initialization logic for debug instances + var env = cc.env(name + '_') - if (typeof createDebug.init === 'function') { - createDebug.init(debug); + var configs = [defaults] + var configFiles = [] + function addConfigFile (file) { + if (configFiles.indexOf(file) >= 0) return + var fileConfig = cc.file(file) + if (fileConfig) { + configs.push(parse(fileConfig)) + configFiles.push(file) } - - createDebug.instances.push(debug); - return debug; } - function destroy() { - var index = createDebug.instances.indexOf(this); + // which files do we look at? + if (!win) + [join(etc, name, 'config'), + join(etc, name + 'rc')].forEach(addConfigFile) + if (home) + [join(home, '.config', name, 'config'), + join(home, '.config', name), + join(home, '.' + name, 'config'), + join(home, '.' + name + 'rc')].forEach(addConfigFile) + addConfigFile(cc.find('.'+name+'rc')) + if (env.config) addConfigFile(env.config) + if (argv.config) addConfigFile(argv.config) - if (index !== -1) { - createDebug.instances.splice(index, 1); - return true; - } + return deepExtend.apply(null, configs.concat([ + env, + argv, + configFiles.length ? {configs: configFiles, config: configFiles[configFiles.length - 1]} : undefined, + ])) +} - return false; - } - function extend(namespace, delimiter) { - return createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); - } - /** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ +/***/ }), +/* 264 */ +/***/ (function(module, exports, __webpack_require__) { +"use strict"; - function enable(namespaces) { - createDebug.save(namespaces); - createDebug.names = []; - createDebug.skips = []; - var i; - var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - var len = split.length; +var fs = __webpack_require__(4) +var ini = __webpack_require__(265) +var path = __webpack_require__(20) +var stripJsonComments = __webpack_require__(266) - for (i = 0; i < len; i++) { - if (!split[i]) { - // ignore empty strings - continue; - } +var parse = exports.parse = function (content) { - namespaces = split[i].replace(/\*/g, '.*?'); + //if it ends in .json or starts with { then it must be json. + //must be done this way, because ini accepts everything. + //can't just try and parse it and let it throw if it's not ini. + //everything is ini. even json with a syntax error. - if (namespaces[0] === '-') { - createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - createDebug.names.push(new RegExp('^' + namespaces + '$')); - } - } + if(/^\s*{/.test(content)) + return JSON.parse(stripJsonComments(content)) + return ini.parse(content) - for (i = 0; i < createDebug.instances.length; i++) { - var instance = createDebug.instances[i]; - instance.enabled = createDebug.enabled(instance.namespace); - } - } - /** - * Disable debug output. - * - * @api public - */ +} +var file = exports.file = function () { + var args = [].slice.call(arguments).filter(function (arg) { return arg != null }) - function disable() { - createDebug.enable(''); - } - /** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ + //path.join breaks if it's a not a string, so just skip this. + for(var i in args) + if('string' !== typeof args[i]) + return + var file = path.join.apply(null, args) + var content + try { + return fs.readFileSync(file,'utf-8') + } catch (err) { + return + } +} - function enabled(name) { - if (name[name.length - 1] === '*') { - return true; - } +var json = exports.json = function () { + var content = file.apply(null, arguments) + return content ? parse(content) : null +} - var i; - var len; +var env = exports.env = function (prefix, env) { + env = env || process.env + var obj = {} + var l = prefix.length + for(var k in env) { + if(k.toLowerCase().indexOf(prefix.toLowerCase()) === 0) { - for (i = 0, len = createDebug.skips.length; i < len; i++) { - if (createDebug.skips[i].test(name)) { - return false; - } - } + var keypath = k.substring(l).split('__') - for (i = 0, len = createDebug.names.length; i < len; i++) { - if (createDebug.names[i].test(name)) { - return true; + // Trim empty strings from keypath array + var _emptyStringIndex + while ((_emptyStringIndex=keypath.indexOf('')) > -1) { + keypath.splice(_emptyStringIndex, 1) } - } - - return false; - } - /** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ + var cursor = obj + keypath.forEach(function _buildSubObj(_subkey,i){ - function coerce(val) { - if (val instanceof Error) { - return val.stack || val.message; - } + // (check for _subkey first so we ignore empty strings) + // (check for cursor to avoid assignment to primitive objects) + if (!_subkey || typeof cursor !== 'object') + return - return val; - } + // If this is the last key, just stuff the value in there + // Assigns actual value from env variable to final key + // (unless it's just an empty string- in that case use the last valid key) + if (i === keypath.length-1) + cursor[_subkey] = env[k] - createDebug.enable(createDebug.load()); - return createDebug; -} -module.exports = setup; + // Build sub-object if nothing already exists at the keypath + if (cursor[_subkey] === undefined) + cursor[_subkey] = {} + // Increment cursor used to track the object at the current depth + cursor = cursor[_subkey] + }) -/***/ }), -/* 275 */ -/***/ (function(module, exports, __webpack_require__) { + } -"use strict"; + } + return obj +} -/** - * Module dependencies. - */ -var tty = __webpack_require__(11); +var find = exports.find = function () { + var rel = path.join.apply(null, [].slice.call(arguments)) -var util = __webpack_require__(12); -/** - * This is the Node.js implementation of `debug()`. - */ + function find(start, rel) { + var file = path.join(start, rel) + try { + fs.statSync(file) + return file + } catch (err) { + if(path.dirname(start) !== start) // root + return find(path.dirname(start), rel) + } + } + return find(process.cwd(), rel) +} -exports.init = init; -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -/** - * Colors. - */ -exports.colors = [6, 2, 3, 4, 5, 1]; -try { - // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) - // eslint-disable-next-line import/no-extraneous-dependencies - var supportsColor = __webpack_require__(13); +/***/ }), +/* 265 */ +/***/ (function(module, exports) { - if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { - exports.colors = [20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68, 69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134, 135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 214, 215, 220, 221]; - } -} catch (error) {} // Swallow - we only care if `supports-color` is available; it doesn't have to be. +exports.parse = exports.decode = decode -/** - * Build up the default `inspectOpts` object from the environment variables. - * - * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js - */ +exports.stringify = exports.encode = encode +exports.safe = safe +exports.unsafe = unsafe -exports.inspectOpts = Object.keys(process.env).filter(function (key) { - return /^debug_/i.test(key); -}).reduce(function (obj, key) { - // Camel-case - var prop = key.substring(6).toLowerCase().replace(/_([a-z])/g, function (_, k) { - return k.toUpperCase(); - }); // Coerce string value into JS value +var eol = typeof process !== 'undefined' && + process.platform === 'win32' ? '\r\n' : '\n' - var val = process.env[key]; +function encode (obj, opt) { + var children = [] + var out = '' - if (/^(yes|on|true|enabled)$/i.test(val)) { - val = true; - } else if (/^(no|off|false|disabled)$/i.test(val)) { - val = false; - } else if (val === 'null') { - val = null; + if (typeof opt === 'string') { + opt = { + section: opt, + whitespace: false + } } else { - val = Number(val); + opt = opt || {} + opt.whitespace = opt.whitespace === true } - obj[prop] = val; - return obj; -}, {}); -/** - * Is stdout a TTY? Colored output is enabled when `true`. - */ + var separator = opt.whitespace ? ' = ' : '=' -function useColors() { - return 'colors' in exports.inspectOpts ? Boolean(exports.inspectOpts.colors) : tty.isatty(process.stderr.fd); -} -/** - * Adds ANSI color escape codes if enabled. - * - * @api public - */ + Object.keys(obj).forEach(function (k, _, __) { + var val = obj[k] + if (val && Array.isArray(val)) { + val.forEach(function (item) { + out += safe(k + '[]') + separator + safe(item) + '\n' + }) + } else if (val && typeof val === 'object') { + children.push(k) + } else { + out += safe(k) + separator + safe(val) + eol + } + }) + if (opt.section && out.length) { + out = '[' + safe(opt.section) + ']' + eol + out + } -function formatArgs(args) { - var name = this.namespace, - useColors = this.useColors; + children.forEach(function (k, _, __) { + var nk = dotSplit(k).join('\\.') + var section = (opt.section ? opt.section + '.' : '') + nk + var child = encode(obj[k], { + section: section, + whitespace: opt.whitespace + }) + if (out.length && child.length) { + out += eol + } + out += child + }) - if (useColors) { - var c = this.color; - var colorCode = "\x1B[3" + (c < 8 ? c : '8;5;' + c); - var prefix = " ".concat(colorCode, ";1m").concat(name, " \x1B[0m"); - args[0] = prefix + args[0].split('\n').join('\n' + prefix); - args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + "\x1B[0m"); - } else { - args[0] = getDate() + name + ' ' + args[0]; - } + return out } -function getDate() { - if (exports.inspectOpts.hideDate) { - return ''; - } - - return new Date().toISOString() + ' '; +function dotSplit (str) { + return str.replace(/\1/g, '\u0002LITERAL\\1LITERAL\u0002') + .replace(/\\\./g, '\u0001') + .split(/\./).map(function (part) { + return part.replace(/\1/g, '\\.') + .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001') + }) } -/** - * Invokes `util.format()` with the specified arguments and writes to stderr. - */ +function decode (str) { + var out = {} + var p = out + var section = null + // section |key = value + var re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i + var lines = str.split(/[\r\n]+/g) -function log() { - return process.stderr.write(util.format.apply(util, arguments) + '\n'); -} -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ + lines.forEach(function (line, _, __) { + if (!line || line.match(/^\s*[;#]/)) return + var match = line.match(re) + if (!match) return + if (match[1] !== undefined) { + section = unsafe(match[1]) + p = out[section] = out[section] || {} + return + } + var key = unsafe(match[2]) + var value = match[3] ? unsafe(match[4]) : true + switch (value) { + case 'true': + case 'false': + case 'null': value = JSON.parse(value) + } + // Convert keys with '[]' suffix to an array + if (key.length > 2 && key.slice(-2) === '[]') { + key = key.substring(0, key.length - 2) + if (!p[key]) { + p[key] = [] + } else if (!Array.isArray(p[key])) { + p[key] = [p[key]] + } + } -function save(namespaces) { - if (namespaces) { - process.env.DEBUG = namespaces; - } else { - // If you set a process.env field to null or undefined, it gets cast to the - // string 'null' or 'undefined'. Just delete instead. - delete process.env.DEBUG; - } -} -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ + // safeguard against resetting a previously defined + // array by accidentally forgetting the brackets + if (Array.isArray(p[key])) { + p[key].push(value) + } else { + p[key] = value + } + }) + // {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}} + // use a filter to return the keys that have to be deleted. + Object.keys(out).filter(function (k, _, __) { + if (!out[k] || + typeof out[k] !== 'object' || + Array.isArray(out[k])) { + return false + } + // see if the parent section is also an object. + // if so, add it to that, and mark this one for deletion + var parts = dotSplit(k) + var p = out + var l = parts.pop() + var nl = l.replace(/\\\./g, '.') + parts.forEach(function (part, _, __) { + if (!p[part] || typeof p[part] !== 'object') p[part] = {} + p = p[part] + }) + if (p === out && nl === l) { + return false + } + p[nl] = out[k] + return true + }).forEach(function (del, _, __) { + delete out[del] + }) -function load() { - return process.env.DEBUG; + return out } -/** - * Init logic for `debug` instances. - * - * Create a new `inspectOpts` object in case `useColors` is set - * differently for a particular `debug` instance. - */ +function isQuoted (val) { + return (val.charAt(0) === '"' && val.slice(-1) === '"') || + (val.charAt(0) === "'" && val.slice(-1) === "'") +} -function init(debug) { - debug.inspectOpts = {}; - var keys = Object.keys(exports.inspectOpts); +function safe (val) { + return (typeof val !== 'string' || + val.match(/[=\r\n]/) || + val.match(/^\[/) || + (val.length > 1 && + isQuoted(val)) || + val !== val.trim()) + ? JSON.stringify(val) + : val.replace(/;/g, '\\;').replace(/#/g, '\\#') +} - for (var i = 0; i < keys.length; i++) { - debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; +function unsafe (val, doUnesc) { + val = (val || '').trim() + if (isQuoted(val)) { + // remove the single quotes before calling JSON.parse + if (val.charAt(0) === "'") { + val = val.substr(1, val.length - 2) + } + try { val = JSON.parse(val) } catch (_) {} + } else { + // walk the val to find the first not-escaped ; character + var esc = false + var unesc = '' + for (var i = 0, l = val.length; i < l; i++) { + var c = val.charAt(i) + if (esc) { + if ('\\;#'.indexOf(c) !== -1) { + unesc += c + } else { + unesc += '\\' + c + } + esc = false + } else if (';#'.indexOf(c) !== -1) { + break + } else if (c === '\\') { + esc = true + } else { + unesc += c + } + } + if (esc) { + unesc += '\\' + } + return unesc.trim() } + return val } -module.exports = __webpack_require__(274)(exports); -var formatters = module.exports.formatters; -/** - * Map %o to `util.inspect()`, all on a single line. - */ - -formatters.o = function (v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts).replace(/\s*\n\s*/g, ' '); -}; -/** - * Map %O to `util.inspect()`, allowing multiple lines if needed. - */ - - -formatters.O = function (v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts); -}; - - /***/ }), -/* 276 */ +/* 266 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +var singleComment = 1; +var multiComment = 2; -// high-level commands -exports.c = exports.create = __webpack_require__(277) -exports.r = exports.replace = __webpack_require__(301) -exports.t = exports.list = __webpack_require__(299) -exports.u = exports.update = __webpack_require__(302) -exports.x = exports.extract = __webpack_require__(303) - -// classes -exports.Pack = __webpack_require__(279) -exports.Unpack = __webpack_require__(304) -exports.Parse = __webpack_require__(300) -exports.ReadEntry = __webpack_require__(289) -exports.WriteEntry = __webpack_require__(291) -exports.Header = __webpack_require__(293) -exports.Pax = __webpack_require__(292) -exports.types = __webpack_require__(290) - +function stripWithoutWhitespace() { + return ''; +} -/***/ }), -/* 277 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -// tar -c -const hlo = __webpack_require__(278) - -const Pack = __webpack_require__(279) -const fs = __webpack_require__(4) -const fsm = __webpack_require__(298) -const t = __webpack_require__(299) -const path = __webpack_require__(20) - -const c = module.exports = (opt_, files, cb) => { - if (typeof files === 'function') - cb = files +function stripWithWhitespace(str, start, end) { + return str.slice(start, end).replace(/\S/g, ' '); +} - if (Array.isArray(opt_)) - files = opt_, opt_ = {} +module.exports = function (str, opts) { + opts = opts || {}; - if (!files || !Array.isArray(files) || !files.length) - throw new TypeError('no files or directories specified') + var currentChar; + var nextChar; + var insideString = false; + var insideComment = false; + var offset = 0; + var ret = ''; + var strip = opts.whitespace === false ? stripWithoutWhitespace : stripWithWhitespace; - files = Array.from(files) + for (var i = 0; i < str.length; i++) { + currentChar = str[i]; + nextChar = str[i + 1]; - const opt = hlo(opt_) + if (!insideComment && currentChar === '"') { + var escaped = str[i - 1] === '\\' && str[i - 2] !== '\\'; + if (!escaped) { + insideString = !insideString; + } + } - if (opt.sync && typeof cb === 'function') - throw new TypeError('callback not supported for sync tar functions') + if (insideString) { + continue; + } - if (!opt.file && typeof cb === 'function') - throw new TypeError('callback only supported with file option') + if (!insideComment && currentChar + nextChar === '//') { + ret += str.slice(offset, i); + offset = i; + insideComment = singleComment; + i++; + } else if (insideComment === singleComment && currentChar + nextChar === '\r\n') { + i++; + insideComment = false; + ret += strip(str, offset, i); + offset = i; + continue; + } else if (insideComment === singleComment && currentChar === '\n') { + insideComment = false; + ret += strip(str, offset, i); + offset = i; + } else if (!insideComment && currentChar + nextChar === '/*') { + ret += str.slice(offset, i); + offset = i; + insideComment = multiComment; + i++; + continue; + } else if (insideComment === multiComment && currentChar + nextChar === '*/') { + i++; + insideComment = false; + ret += strip(str, offset, i + 1); + offset = i + 1; + continue; + } + } - return opt.file && opt.sync ? createFileSync(opt, files) - : opt.file ? createFile(opt, files, cb) - : opt.sync ? createSync(opt, files) - : create(opt, files) -} + return ret + (insideComment ? strip(str.substr(offset)) : str.substr(offset)); +}; -const createFileSync = (opt, files) => { - const p = new Pack.Sync(opt) - const stream = new fsm.WriteStreamSync(opt.file, { - mode: opt.mode || 0o666 - }) - p.pipe(stream) - addFilesSync(p, files) -} -const createFile = (opt, files, cb) => { - const p = new Pack(opt) - const stream = new fsm.WriteStream(opt.file, { - mode: opt.mode || 0o666 - }) - p.pipe(stream) +/***/ }), +/* 267 */ +/***/ (function(module, exports, __webpack_require__) { - const promise = new Promise((res, rej) => { - stream.on('error', rej) - stream.on('close', res) - p.on('error', rej) - }) +"use strict"; +/*! + * @description Recursive object extending + * @author Viacheslav Lotsmanov + * @license MIT + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2018 Viacheslav Lotsmanov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ - addFilesAsync(p, files) - return cb ? promise.then(cb, cb) : promise -} -const addFilesSync = (p, files) => { - files.forEach(file => { - if (file.charAt(0) === '@') - t({ - file: path.resolve(p.cwd, file.substr(1)), - sync: true, - noResume: true, - onentry: entry => p.add(entry) - }) - else - p.add(file) - }) - p.end() +function isSpecificValue(val) { + return ( + val instanceof Buffer + || val instanceof Date + || val instanceof RegExp + ) ? true : false; } -const addFilesAsync = (p, files) => { - while (files.length) { - const file = files.shift() - if (file.charAt(0) === '@') - return t({ - file: path.resolve(p.cwd, file.substr(1)), - noResume: true, - onentry: entry => p.add(entry) - }).then(_ => addFilesAsync(p, files)) - else - p.add(file) - } - p.end() +function cloneSpecificValue(val) { + if (val instanceof Buffer) { + var x = Buffer.alloc + ? Buffer.alloc(val.length) + : new Buffer(val.length); + val.copy(x); + return x; + } else if (val instanceof Date) { + return new Date(val.getTime()); + } else if (val instanceof RegExp) { + return new RegExp(val); + } else { + throw new Error('Unexpected situation'); + } } -const createSync = (opt, files) => { - const p = new Pack.Sync(opt) - addFilesSync(p, files) - return p +/** + * Recursive cloning array. + */ +function deepCloneArray(arr) { + var clone = []; + arr.forEach(function (item, index) { + if (typeof item === 'object' && item !== null) { + if (Array.isArray(item)) { + clone[index] = deepCloneArray(item); + } else if (isSpecificValue(item)) { + clone[index] = cloneSpecificValue(item); + } else { + clone[index] = deepExtend({}, item); + } + } else { + clone[index] = item; + } + }); + return clone; } -const create = (opt, files) => { - const p = new Pack(opt) - addFilesAsync(p, files) - return p +function safeGetProperty(object, property) { + return property === '__proto__' ? undefined : object[property]; } +/** + * Extening object that entered in first argument. + * + * Returns extended object or false if have no target object or incorrect type. + * + * If you wish to clone source object (without modify it), just use empty new + * object as first argument, like this: + * deepExtend({}, yourObj_1, [yourObj_N]); + */ +var deepExtend = module.exports = function (/*obj_1, [obj_2], [obj_N]*/) { + if (arguments.length < 1 || typeof arguments[0] !== 'object') { + return false; + } -/***/ }), -/* 278 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - + if (arguments.length < 2) { + return arguments[0]; + } -// turn tar(1) style args like `C` into the more verbose things like `cwd` + var target = arguments[0]; -const argmap = new Map([ - ['C', 'cwd'], - ['f', 'file'], - ['z', 'gzip'], - ['P', 'preservePaths'], - ['U', 'unlink'], - ['strip-components', 'strip'], - ['stripComponents', 'strip'], - ['keep-newer', 'newer'], - ['keepNewer', 'newer'], - ['keep-newer-files', 'newer'], - ['keepNewerFiles', 'newer'], - ['k', 'keep'], - ['keep-existing', 'keep'], - ['keepExisting', 'keep'], - ['m', 'noMtime'], - ['no-mtime', 'noMtime'], - ['p', 'preserveOwner'], - ['L', 'follow'], - ['h', 'follow'] -]) + // convert arguments to array and cut off target object + var args = Array.prototype.slice.call(arguments, 1); -const parse = module.exports = opt => opt ? Object.keys(opt).map(k => [ - argmap.has(k) ? argmap.get(k) : k, opt[k] -]).reduce((set, kv) => (set[kv[0]] = kv[1], set), Object.create(null)) : {} + var val, src, clone; + args.forEach(function (obj) { + // skip argument if isn't an object, is null, or is an array + if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) { + return; + } -/***/ }), -/* 279 */ -/***/ (function(module, exports, __webpack_require__) { + Object.keys(obj).forEach(function (key) { + src = safeGetProperty(target, key); // source value + val = safeGetProperty(obj, key); // new value -"use strict"; + // recursion prevention + if (val === target) { + return; + /** + * if new value isn't object then just overwrite by new value + * instead of extending. + */ + } else if (typeof val !== 'object' || val === null) { + target[key] = val; + return; -const Buffer = __webpack_require__(280) + // just clone arrays (and recursive clone objects inside) + } else if (Array.isArray(val)) { + target[key] = deepCloneArray(val); + return; -// A readable tar stream creator -// Technically, this is a transform stream that you write paths into, -// and tar format comes out of. -// The `add()` method is like `write()` but returns this, -// and end() return `this` as well, so you can -// do `new Pack(opt).add('files').add('dir').end().pipe(output) -// You could also do something like: -// streamOfPaths().pipe(new Pack()).pipe(new fs.WriteStream('out.tar')) + // custom cloning and overwrite for specific objects + } else if (isSpecificValue(val)) { + target[key] = cloneSpecificValue(val); + return; -class PackJob { - constructor (path, absolute) { - this.path = path || './' - this.absolute = absolute - this.entry = null - this.stat = null - this.readdir = null - this.pending = false - this.ignore = false - this.piped = false - } -} + // overwrite by new value if source isn't object or array + } else if (typeof src !== 'object' || src === null || Array.isArray(src)) { + target[key] = deepExtend({}, val); + return; -const MiniPass = __webpack_require__(283) -const zlib = __webpack_require__(287) -const ReadEntry = __webpack_require__(289) -const WriteEntry = __webpack_require__(291) -const WriteEntrySync = WriteEntry.Sync -const WriteEntryTar = WriteEntry.Tar -const Yallist = __webpack_require__(284) -const EOF = Buffer.alloc(1024) -const ONSTAT = Symbol('onStat') -const ENDED = Symbol('ended') -const QUEUE = Symbol('queue') -const CURRENT = Symbol('current') -const PROCESS = Symbol('process') -const PROCESSING = Symbol('processing') -const PROCESSJOB = Symbol('processJob') -const JOBS = Symbol('jobs') -const JOBDONE = Symbol('jobDone') -const ADDFSENTRY = Symbol('addFSEntry') -const ADDTARENTRY = Symbol('addTarEntry') -const STAT = Symbol('stat') -const READDIR = Symbol('readdir') -const ONREADDIR = Symbol('onreaddir') -const PIPE = Symbol('pipe') -const ENTRY = Symbol('entry') -const ENTRYOPT = Symbol('entryOpt') -const WRITEENTRYCLASS = Symbol('writeEntryClass') -const WRITE = Symbol('write') -const ONDRAIN = Symbol('ondrain') + // source value and new value is objects both, extending... + } else { + target[key] = deepExtend(src, val); + return; + } + }); + }); -const fs = __webpack_require__(4) -const path = __webpack_require__(20) -const warner = __webpack_require__(295) + return target; +}; -const Pack = warner(class Pack extends MiniPass { - constructor (opt) { - super(opt) - opt = opt || Object.create(null) - this.opt = opt - this.cwd = opt.cwd || process.cwd() - this.maxReadSize = opt.maxReadSize - this.preservePaths = !!opt.preservePaths - this.strict = !!opt.strict - this.noPax = !!opt.noPax - this.prefix = (opt.prefix || '').replace(/(\\|\/)+$/, '') - this.linkCache = opt.linkCache || new Map() - this.statCache = opt.statCache || new Map() - this.readdirCache = opt.readdirCache || new Map() - this[WRITEENTRYCLASS] = WriteEntry - if (typeof opt.onwarn === 'function') - this.on('warn', opt.onwarn) +/***/ }), +/* 268 */ +/***/ (function(module, exports) { - this.zip = null - if (opt.gzip) { - if (typeof opt.gzip !== 'object') - opt.gzip = {} - this.zip = new zlib.Gzip(opt.gzip) - this.zip.on('data', chunk => super.write(chunk)) - this.zip.on('end', _ => super.end()) - this.zip.on('drain', _ => this[ONDRAIN]()) - this.on('resume', _ => this.zip.resume()) - } else - this.on('drain', this[ONDRAIN]) +module.exports = function (args, opts) { + if (!opts) opts = {}; + + var flags = { bools : {}, strings : {}, unknownFn: null }; - this.portable = !!opt.portable - this.noDirRecurse = !!opt.noDirRecurse - this.follow = !!opt.follow - this.noMtime = !!opt.noMtime - this.mtime = opt.mtime || null + if (typeof opts['unknown'] === 'function') { + flags.unknownFn = opts['unknown']; + } - this.filter = typeof opt.filter === 'function' ? opt.filter : _ => true + if (typeof opts['boolean'] === 'boolean' && opts['boolean']) { + flags.allBools = true; + } else { + [].concat(opts['boolean']).filter(Boolean).forEach(function (key) { + flags.bools[key] = true; + }); + } + + var aliases = {}; + Object.keys(opts.alias || {}).forEach(function (key) { + aliases[key] = [].concat(opts.alias[key]); + aliases[key].forEach(function (x) { + aliases[x] = [key].concat(aliases[key].filter(function (y) { + return x !== y; + })); + }); + }); - this[QUEUE] = new Yallist - this[JOBS] = 0 - this.jobs = +opt.jobs || 4 - this[PROCESSING] = false - this[ENDED] = false - } + [].concat(opts.string).filter(Boolean).forEach(function (key) { + flags.strings[key] = true; + if (aliases[key]) { + flags.strings[aliases[key]] = true; + } + }); - [WRITE] (chunk) { - return super.write(chunk) - } + var defaults = opts['default'] || {}; + + var argv = { _ : [] }; + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] === undefined ? false : defaults[key]); + }); + + var notFlags = []; - add (path) { - this.write(path) - return this - } + if (args.indexOf('--') !== -1) { + notFlags = args.slice(args.indexOf('--')+1); + args = args.slice(0, args.indexOf('--')); + } - end (path) { - if (path) - this.write(path) - this[ENDED] = true - this[PROCESS]() - return this - } + function argDefined(key, arg) { + return (flags.allBools && /^--[^=]+$/.test(arg)) || + flags.strings[key] || flags.bools[key] || aliases[key]; + } - write (path) { - if (this[ENDED]) - throw new Error('write after end') + function setArg (key, val, arg) { + if (arg && flags.unknownFn && !argDefined(key, arg)) { + if (flags.unknownFn(arg) === false) return; + } - if (path instanceof ReadEntry) - this[ADDTARENTRY](path) - else - this[ADDFSENTRY](path) - return this.flowing - } + var value = !flags.strings[key] && isNumber(val) + ? Number(val) : val + ; + setKey(argv, key.split('.'), value); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), value); + }); + } - [ADDTARENTRY] (p) { - const absolute = path.resolve(this.cwd, p.path) - if (this.prefix) - p.path = this.prefix + '/' + p.path.replace(/^\.(\/+|$)/, '') + function setKey (obj, keys, value) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + if (o[key] === undefined) o[key] = {}; + o = o[key]; + }); - // in this case, we don't have to wait for the stat - if (!this.filter(p.path, p)) - p.resume() - else { - const job = new PackJob(p.path, absolute, false) - job.entry = new WriteEntryTar(p, this[ENTRYOPT](job)) - job.entry.on('end', _ => this[JOBDONE](job)) - this[JOBS] += 1 - this[QUEUE].push(job) + var key = keys[keys.length - 1]; + if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') { + o[key] = value; + } + else if (Array.isArray(o[key])) { + o[key].push(value); + } + else { + o[key] = [ o[key], value ]; + } + } + + function aliasIsBoolean(key) { + return aliases[key].some(function (x) { + return flags.bools[x]; + }); } - this[PROCESS]() - } - - [ADDFSENTRY] (p) { - const absolute = path.resolve(this.cwd, p) - if (this.prefix) - p = this.prefix + '/' + p.replace(/^\.(\/+|$)/, '') + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + + if (/^--.+=/.test(arg)) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + var m = arg.match(/^--([^=]+)=([\s\S]*)$/); + var key = m[1]; + var value = m[2]; + if (flags.bools[key]) { + value = value !== 'false'; + } + setArg(key, value, arg); + } + else if (/^--no-.+/.test(arg)) { + var key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false, arg); + } + else if (/^--.+/.test(arg)) { + var key = arg.match(/^--(.+)/)[1]; + var next = args[i + 1]; + if (next !== undefined && !/^-/.test(next) + && !flags.bools[key] + && !flags.allBools + && (aliases[key] ? !aliasIsBoolean(key) : true)) { + setArg(key, next, arg); + i++; + } + else if (/^(true|false)$/.test(next)) { + setArg(key, next === 'true', arg); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + else if (/^-[^-]+/.test(arg)) { + var letters = arg.slice(1,-1).split(''); + + var broken = false; + for (var j = 0; j < letters.length; j++) { + var next = arg.slice(j+2); + + if (next === '-') { + setArg(letters[j], next, arg) + continue; + } + + if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) { + setArg(letters[j], next.split('=')[1], arg); + broken = true; + break; + } + + if (/[A-Za-z]/.test(letters[j]) + && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { + setArg(letters[j], next, arg); + broken = true; + break; + } + + if (letters[j+1] && letters[j+1].match(/\W/)) { + setArg(letters[j], arg.slice(j+2), arg); + broken = true; + break; + } + else { + setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg); + } + } + + var key = arg.slice(-1)[0]; + if (!broken && key !== '-') { + if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1]) + && !flags.bools[key] + && (aliases[key] ? !aliasIsBoolean(key) : true)) { + setArg(key, args[i+1], arg); + i++; + } + else if (args[i+1] && /true|false/.test(args[i+1])) { + setArg(key, args[i+1] === 'true', arg); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + } + else { + if (!flags.unknownFn || flags.unknownFn(arg) !== false) { + argv._.push( + flags.strings['_'] || !isNumber(arg) ? arg : Number(arg) + ); + } + if (opts.stopEarly) { + argv._.push.apply(argv._, args.slice(i + 1)); + break; + } + } + } + + Object.keys(defaults).forEach(function (key) { + if (!hasKey(argv, key.split('.'))) { + setKey(argv, key.split('.'), defaults[key]); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), defaults[key]); + }); + } + }); + + if (opts['--']) { + argv['--'] = new Array(); + notFlags.forEach(function(key) { + argv['--'].push(key); + }); + } + else { + notFlags.forEach(function(key) { + argv._.push(key); + }); + } - this[QUEUE].push(new PackJob(p, absolute)) - this[PROCESS]() - } + return argv; +}; - [STAT] (job) { - job.pending = true - this[JOBS] += 1 - const stat = this.follow ? 'stat' : 'lstat' - fs[stat](job.absolute, (er, stat) => { - job.pending = false - this[JOBS] -= 1 - if (er) - this.emit('error', er) - else - this[ONSTAT](job, stat) - }) - } +function hasKey (obj, keys) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + o = (o[key] || {}); + }); - [ONSTAT] (job, stat) { - this.statCache.set(job.absolute, stat) - job.stat = stat + var key = keys[keys.length - 1]; + return key in o; +} - // now we have the stat, we can filter it. - if (!this.filter(job.path, stat)) - job.ignore = true +function isNumber (x) { + if (typeof x === 'number') return true; + if (/^0x[0-9a-f]+$/i.test(x)) return true; + return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x); +} - this[PROCESS]() - } - [READDIR] (job) { - job.pending = true - this[JOBS] += 1 - fs.readdir(job.absolute, (er, entries) => { - job.pending = false - this[JOBS] -= 1 - if (er) - return this.emit('error', er) - this[ONREADDIR](job, entries) - }) - } - [ONREADDIR] (job, entries) { - this.readdirCache.set(job.absolute, entries) - job.readdir = entries - this[PROCESS]() - } +/***/ }), +/* 269 */ +/***/ (function(module, exports) { - [PROCESS] () { - if (this[PROCESSING]) - return +module.exports = require("url"); - this[PROCESSING] = true - for (let w = this[QUEUE].head; - w !== null && this[JOBS] < this.jobs; - w = w.next) { - this[PROCESSJOB](w.value) - if (w.value.ignore) { - const p = w.next - this[QUEUE].removeNode(w) - w.next = p - } - } +/***/ }), +/* 270 */ +/***/ (function(module, exports, __webpack_require__) { - this[PROCESSING] = false +"use strict"; - if (this[ENDED] && !this[QUEUE].length && this[JOBS] === 0) { - if (this.zip) - this.zip.end(EOF) - else { - super.write(EOF) - super.end() - } +Object.defineProperty(exports, "__esModule", { value: true }); +const tslib_1 = __webpack_require__(3); +const follow_redirects_1 = __webpack_require__(271); +const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); +const mkdirp_1 = tslib_1.__importDefault(__webpack_require__(182)); +const path_1 = tslib_1.__importDefault(__webpack_require__(20)); +const tar_1 = tslib_1.__importDefault(__webpack_require__(278)); +const url_1 = __webpack_require__(269); +const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); +const fetch_1 = __webpack_require__(309); +/** + * Download and extract tgz from url + * + * @param {string} url + * @param {DownloadOptions} options contains dest folder and optional onProgress callback + */ +function download(url, options) { + const rejectUnauthorized = workspace_1.default.getConfiguration('https').get('rejectUnauthorized', true); + let { dest, onProgress } = options; + if (!dest || !path_1.default.isAbsolute(dest)) { + throw new Error(`Expect absolute file path for dest option.`); } - } + if (!fs_1.default.existsSync(dest)) + mkdirp_1.default.sync(dest); + let endpoint = url_1.parse(url); + let mod = url.startsWith('https') ? follow_redirects_1.https : follow_redirects_1.http; + let agent = fetch_1.getAgent(endpoint); + let opts = Object.assign({ + method: 'GET', + hostname: endpoint.hostname, + port: endpoint.port ? parseInt(endpoint.port, 10) : (endpoint.protocol === 'https:' ? 443 : 80), + path: endpoint.path, + protocol: url.startsWith('https') ? 'https:' : 'http:', + agent, + rejectUnauthorized, + headers: { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64)' + } + }, options); + return new Promise((resolve, reject) => { + const req = mod.request(opts, (res) => { + if (res.statusCode != 200) { + reject(new Error(`Invalid response from ${url}: ${res.statusCode}`)); + return; + } + if (onProgress) { + const len = parseInt(res.headers['content-length'], 10); + let cur = 0; + if (!isNaN(len)) { + res.on('data', chunk => { + cur += chunk.length; + onProgress(cur / len); + }); + } + } + let stream = res.pipe(tar_1.default.x({ strip: 1, C: dest })); + stream.on('finish', () => { + setTimeout(resolve, 100); + }); + stream.on('error', reject); + }); + req.on('error', reject); + req.end(); + }); +} +exports.default = download; +//# sourceMappingURL=download.js.map - get [CURRENT] () { - return this[QUEUE] && this[QUEUE].head && this[QUEUE].head.value - } +/***/ }), +/* 271 */ +/***/ (function(module, exports, __webpack_require__) { - [JOBDONE] (job) { - this[QUEUE].shift() - this[JOBS] -= 1 - this[PROCESS]() - } +var url = __webpack_require__(269); +var URL = url.URL; +var http = __webpack_require__(272); +var https = __webpack_require__(273); +var assert = __webpack_require__(46); +var Writable = __webpack_require__(44).Writable; +var debug = __webpack_require__(274)("follow-redirects"); - [PROCESSJOB] (job) { - if (job.pending) - return +// RFC7231§4.2.1: Of the request methods defined by this specification, +// the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe. +var SAFE_METHODS = { GET: true, HEAD: true, OPTIONS: true, TRACE: true }; - if (job.entry) { - if (job === this[CURRENT] && !job.piped) - this[PIPE](job) - return - } +// Create handlers that pass events from native requests +var eventHandlers = Object.create(null); +["abort", "aborted", "connect", "error", "socket", "timeout"].forEach(function (event) { + eventHandlers[event] = function (arg1, arg2, arg3) { + this._redirectable.emit(event, arg1, arg2, arg3); + }; +}); - if (!job.stat) { - if (this.statCache.has(job.absolute)) - this[ONSTAT](job, this.statCache.get(job.absolute)) - else - this[STAT](job) - } - if (!job.stat) - return +// An HTTP(S) request that can be redirected +function RedirectableRequest(options, responseCallback) { + // Initialize the request + Writable.call(this); + this._sanitizeOptions(options); + this._options = options; + this._ended = false; + this._ending = false; + this._redirectCount = 0; + this._redirects = []; + this._requestBodyLength = 0; + this._requestBodyBuffers = []; - // filtered out! - if (job.ignore) - return + // Attach a callback if passed + if (responseCallback) { + this.on("response", responseCallback); + } - if (!this.noDirRecurse && job.stat.isDirectory() && !job.readdir) { - if (this.readdirCache.has(job.absolute)) - this[ONREADDIR](job, this.readdirCache.get(job.absolute)) - else - this[READDIR](job) - if (!job.readdir) - return - } + // React to responses of native requests + var self = this; + this._onNativeResponse = function (response) { + self._processResponse(response); + }; - // we know it doesn't have an entry, because that got checked above - job.entry = this[ENTRY](job) - if (!job.entry) { - job.ignore = true - return - } + // Perform the first request + this._performRequest(); +} +RedirectableRequest.prototype = Object.create(Writable.prototype); - if (job === this[CURRENT] && !job.piped) - this[PIPE](job) +// Writes buffered data to the current native request +RedirectableRequest.prototype.write = function (data, encoding, callback) { + // Writing is not allowed if end has been called + if (this._ending) { + throw new Error("write after end"); } - [ENTRYOPT] (job) { - return { - onwarn: (msg, data) => { - this.warn(msg, data) - }, - noPax: this.noPax, - cwd: this.cwd, - absolute: job.absolute, - preservePaths: this.preservePaths, - maxReadSize: this.maxReadSize, - strict: this.strict, - portable: this.portable, - linkCache: this.linkCache, - statCache: this.statCache, - noMtime: this.noMtime, - mtime: this.mtime - } + // Validate input and shift parameters if necessary + if (!(typeof data === "string" || typeof data === "object" && ("length" in data))) { + throw new Error("data should be a string, Buffer or Uint8Array"); + } + if (typeof encoding === "function") { + callback = encoding; + encoding = null; } - [ENTRY] (job) { - this[JOBS] += 1 - try { - return new this[WRITEENTRYCLASS](job.path, this[ENTRYOPT](job)) - .on('end', () => this[JOBDONE](job)) - .on('error', er => this.emit('error', er)) - } catch (er) { - this.emit('error', er) + // Ignore empty buffers, since writing them doesn't invoke the callback + // https://github.com/nodejs/node/issues/22066 + if (data.length === 0) { + if (callback) { + callback(); } + return; } - - [ONDRAIN] () { - if (this[CURRENT] && this[CURRENT].entry) - this[CURRENT].entry.resume() + // Only write when we don't exceed the maximum body length + if (this._requestBodyLength + data.length <= this._options.maxBodyLength) { + this._requestBodyLength += data.length; + this._requestBodyBuffers.push({ data: data, encoding: encoding }); + this._currentRequest.write(data, encoding, callback); + } + // Error when we exceed the maximum body length + else { + this.emit("error", new Error("Request body larger than maxBodyLength limit")); + this.abort(); } +}; - // like .pipe() but using super, because our write() is special - [PIPE] (job) { - job.piped = true +// Ends the current native request +RedirectableRequest.prototype.end = function (data, encoding, callback) { + // Shift parameters if necessary + if (typeof data === "function") { + callback = data; + data = encoding = null; + } + else if (typeof encoding === "function") { + callback = encoding; + encoding = null; + } - if (job.readdir) - job.readdir.forEach(entry => { - const p = this.prefix ? - job.path.slice(this.prefix.length + 1) || './' - : job.path + // Write data if needed and end + if (!data) { + this._ended = this._ending = true; + this._currentRequest.end(null, null, callback); + } + else { + var self = this; + var currentRequest = this._currentRequest; + this.write(data, encoding, function () { + self._ended = true; + currentRequest.end(null, null, callback); + }); + this._ending = true; + } +}; - const base = p === './' ? '' : p.replace(/\/*$/, '/') - this[ADDFSENTRY](base + entry) - }) +// Sets a header value on the current native request +RedirectableRequest.prototype.setHeader = function (name, value) { + this._options.headers[name] = value; + this._currentRequest.setHeader(name, value); +}; - const source = job.entry - const zip = this.zip +// Clears a header value on the current native request +RedirectableRequest.prototype.removeHeader = function (name) { + delete this._options.headers[name]; + this._currentRequest.removeHeader(name); +}; - if (zip) - source.on('data', chunk => { - if (!zip.write(chunk)) - source.pause() - }) - else - source.on('data', chunk => { - if (!super.write(chunk)) - source.pause() - }) +// Global timeout for all underlying requests +RedirectableRequest.prototype.setTimeout = function (msecs, callback) { + if (callback) { + this.once("timeout", callback); } - pause () { - if (this.zip) - this.zip.pause() - return super.pause() + if (this.socket) { + startTimer(this, msecs); } -}) - -class PackSync extends Pack { - constructor (opt) { - super(opt) - this[WRITEENTRYCLASS] = WriteEntrySync + else { + var self = this; + this._currentRequest.once("socket", function () { + startTimer(self, msecs); + }); } - // pause/resume are no-ops in sync streams. - pause () {} - resume () {} + this.once("response", clearTimer); + this.once("error", clearTimer); - [STAT] (job) { - const stat = this.follow ? 'statSync' : 'lstatSync' - this[ONSTAT](job, fs[stat](job.absolute)) - } + return this; +}; - [READDIR] (job, stat) { - this[ONREADDIR](job, fs.readdirSync(job.absolute)) - } +function startTimer(request, msecs) { + clearTimeout(request._timeout); + request._timeout = setTimeout(function () { + request.emit("timeout"); + }, msecs); +} - // gotta get it all in this tick - [PIPE] (job) { - const source = job.entry - const zip = this.zip +function clearTimer() { + clearTimeout(this._timeout); +} - if (job.readdir) - job.readdir.forEach(entry => { - const p = this.prefix ? - job.path.slice(this.prefix.length + 1) || './' - : job.path +// Proxy all other public ClientRequest methods +[ + "abort", "flushHeaders", "getHeader", + "setNoDelay", "setSocketKeepAlive", +].forEach(function (method) { + RedirectableRequest.prototype[method] = function (a, b) { + return this._currentRequest[method](a, b); + }; +}); - const base = p === './' ? '' : p.replace(/\/*$/, '/') - this[ADDFSENTRY](base + entry) - }) +// Proxy all public ClientRequest properties +["aborted", "connection", "socket"].forEach(function (property) { + Object.defineProperty(RedirectableRequest.prototype, property, { + get: function () { return this._currentRequest[property]; }, + }); +}); - if (zip) - source.on('data', chunk => { - zip.write(chunk) - }) - else - source.on('data', chunk => { - super[WRITE](chunk) - }) +RedirectableRequest.prototype._sanitizeOptions = function (options) { + // Ensure headers are always present + if (!options.headers) { + options.headers = {}; } -} - -Pack.Sync = PackSync - -module.exports = Pack + // Since http.request treats host as an alias of hostname, + // but the url module interprets host as hostname plus port, + // eliminate the host property to avoid confusion. + if (options.host) { + // Use hostname if set, because it has precedence + if (!options.hostname) { + options.hostname = options.host; + } + delete options.host; + } -/***/ }), -/* 280 */ -/***/ (function(module, exports, __webpack_require__) { + // Complete the URL object when necessary + if (!options.pathname && options.path) { + var searchPos = options.path.indexOf("?"); + if (searchPos < 0) { + options.pathname = options.path; + } + else { + options.pathname = options.path.substring(0, searchPos); + options.search = options.path.substring(searchPos); + } + } +}; -"use strict"; +// Executes the next native request (initial or redirect) +RedirectableRequest.prototype._performRequest = function () { + // Load the native protocol + var protocol = this._options.protocol; + var nativeProtocol = this._options.nativeProtocols[protocol]; + if (!nativeProtocol) { + this.emit("error", new Error("Unsupported protocol " + protocol)); + return; + } -// Buffer in node 4.x < 4.5.0 doesn't have working Buffer.from -// or Buffer.alloc, and Buffer in node 10 deprecated the ctor. -// .M, this is fine .\^/M.. -let B = Buffer -/* istanbul ignore next */ -if (!B.alloc) { - B = __webpack_require__(281).Buffer -} -module.exports = B + // If specified, use the agent corresponding to the protocol + // (HTTP and HTTPS use different types of agents) + if (this._options.agents) { + var scheme = protocol.substr(0, protocol.length - 1); + this._options.agent = this._options.agents[scheme]; + } + // Create the native request + var request = this._currentRequest = + nativeProtocol.request(this._options, this._onNativeResponse); + this._currentUrl = url.format(this._options); -/***/ }), -/* 281 */ -/***/ (function(module, exports, __webpack_require__) { + // Set up event handlers + request._redirectable = this; + for (var event in eventHandlers) { + /* istanbul ignore else */ + if (event) { + request.on(event, eventHandlers[event]); + } + } -/* eslint-disable node/no-deprecated-api */ -var buffer = __webpack_require__(282) -var Buffer = buffer.Buffer + // End a redirected request + // (The first request must be ended explicitly with RedirectableRequest#end) + if (this._isRedirect) { + // Write the request entity and end. + var i = 0; + var self = this; + var buffers = this._requestBodyBuffers; + (function writeNext(error) { + // Only write if this request has not been redirected yet + /* istanbul ignore else */ + if (request === self._currentRequest) { + // Report any write errors + /* istanbul ignore if */ + if (error) { + self.emit("error", error); + } + // Write the next buffer if there are still left + else if (i < buffers.length) { + var buffer = buffers[i++]; + /* istanbul ignore else */ + if (!request.finished) { + request.write(buffer.data, buffer.encoding, writeNext); + } + } + // End the request if `end` has been called on us + else if (self._ended) { + request.end(); + } + } + }()); + } +}; -// alternative to using Object.keys for old browsers -function copyProps (src, dst) { - for (var key in src) { - dst[key] = src[key] +// Processes a response from the current native request +RedirectableRequest.prototype._processResponse = function (response) { + // Store the redirected response + var statusCode = response.statusCode; + if (this._options.trackRedirects) { + this._redirects.push({ + url: this._currentUrl, + headers: response.headers, + statusCode: statusCode, + }); } -} -if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { - module.exports = buffer -} else { - // Copy properties from require('buffer') - copyProps(buffer, exports) - exports.Buffer = SafeBuffer -} -function SafeBuffer (arg, encodingOrOffset, length) { - return Buffer(arg, encodingOrOffset, length) -} + // RFC7231§6.4: The 3xx (Redirection) class of status code indicates + // that further action needs to be taken by the user agent in order to + // fulfill the request. If a Location header field is provided, + // the user agent MAY automatically redirect its request to the URI + // referenced by the Location field value, + // even if the specific status code is not understood. + var location = response.headers.location; + if (location && this._options.followRedirects !== false && + statusCode >= 300 && statusCode < 400) { + // Abort the current request + this._currentRequest.removeAllListeners(); + this._currentRequest.on("error", noop); + this._currentRequest.abort(); + // Discard the remainder of the response to avoid waiting for data + response.destroy(); -// Copy static methods from Buffer -copyProps(Buffer, SafeBuffer) + // RFC7231§6.4: A client SHOULD detect and intervene + // in cyclical redirections (i.e., "infinite" redirection loops). + if (++this._redirectCount > this._options.maxRedirects) { + this.emit("error", new Error("Max redirects exceeded.")); + return; + } -SafeBuffer.from = function (arg, encodingOrOffset, length) { - if (typeof arg === 'number') { - throw new TypeError('Argument must not be a number') - } - return Buffer(arg, encodingOrOffset, length) -} + // RFC7231§6.4: Automatic redirection needs to done with + // care for methods not known to be safe […], + // since the user might not wish to redirect an unsafe request. + // RFC7231§6.4.7: The 307 (Temporary Redirect) status code indicates + // that the target resource resides temporarily under a different URI + // and the user agent MUST NOT change the request method + // if it performs an automatic redirection to that URI. + var header; + var headers = this._options.headers; + if (statusCode !== 307 && !(this._options.method in SAFE_METHODS)) { + this._options.method = "GET"; + // Drop a possible entity and headers related to it + this._requestBodyBuffers = []; + for (header in headers) { + if (/^content-/i.test(header)) { + delete headers[header]; + } + } + } -SafeBuffer.alloc = function (size, fill, encoding) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') - } - var buf = Buffer(size) - if (fill !== undefined) { - if (typeof encoding === 'string') { - buf.fill(fill, encoding) - } else { - buf.fill(fill) + // Drop the Host header, as the redirect might lead to a different host + if (!this._isRedirect) { + for (header in headers) { + if (/^host$/i.test(header)) { + delete headers[header]; + } + } } - } else { - buf.fill(0) + + // Perform the redirected request + var redirectUrl = url.resolve(this._currentUrl, location); + debug("redirecting to", redirectUrl); + Object.assign(this._options, url.parse(redirectUrl)); + if (typeof this._options.beforeRedirect === "function") { + try { + this._options.beforeRedirect.call(null, this._options); + } + catch (err) { + this.emit("error", err); + return; + } + this._sanitizeOptions(this._options); + } + this._isRedirect = true; + this._performRequest(); } - return buf -} + else { + // The response is not a redirect; return it as-is + response.responseUrl = this._currentUrl; + response.redirects = this._redirects; + this.emit("response", response); -SafeBuffer.allocUnsafe = function (size) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') + // Clean up + this._requestBodyBuffers = []; } - return Buffer(size) +}; + +// Wraps the key/value object of protocols with redirect functionality +function wrap(protocols) { + // Default settings + var exports = { + maxRedirects: 21, + maxBodyLength: 10 * 1024 * 1024, + }; + + // Wrap each protocol + var nativeProtocols = {}; + Object.keys(protocols).forEach(function (scheme) { + var protocol = scheme + ":"; + var nativeProtocol = nativeProtocols[protocol] = protocols[scheme]; + var wrappedProtocol = exports[scheme] = Object.create(nativeProtocol); + + // Executes a request, following redirects + wrappedProtocol.request = function (input, options, callback) { + // Parse parameters + if (typeof input === "string") { + var urlStr = input; + try { + input = urlToOptions(new URL(urlStr)); + } + catch (err) { + /* istanbul ignore next */ + input = url.parse(urlStr); + } + } + else if (URL && (input instanceof URL)) { + input = urlToOptions(input); + } + else { + callback = options; + options = input; + input = { protocol: protocol }; + } + if (typeof options === "function") { + callback = options; + options = null; + } + + // Set defaults + options = Object.assign({ + maxRedirects: exports.maxRedirects, + maxBodyLength: exports.maxBodyLength, + }, input, options); + options.nativeProtocols = nativeProtocols; + + assert.equal(options.protocol, protocol, "protocol mismatch"); + debug("options", options); + return new RedirectableRequest(options, callback); + }; + + // Executes a GET request, following redirects + wrappedProtocol.get = function (input, options, callback) { + var request = wrappedProtocol.request(input, options, callback); + request.end(); + return request; + }; + }); + return exports; } -SafeBuffer.allocUnsafeSlow = function (size) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') +/* istanbul ignore next */ +function noop() { /* empty */ } + +// from https://github.com/nodejs/node/blob/master/lib/internal/url.js +function urlToOptions(urlObject) { + var options = { + protocol: urlObject.protocol, + hostname: urlObject.hostname.startsWith("[") ? + /* istanbul ignore next */ + urlObject.hostname.slice(1, -1) : + urlObject.hostname, + hash: urlObject.hash, + search: urlObject.search, + pathname: urlObject.pathname, + path: urlObject.pathname + urlObject.search, + href: urlObject.href, + }; + if (urlObject.port !== "") { + options.port = Number(urlObject.port); } - return buffer.SlowBuffer(size) + return options; } +// Exports +module.exports = wrap({ http: http, https: https }); +module.exports.wrap = wrap; + /***/ }), -/* 282 */ +/* 272 */ /***/ (function(module, exports) { -module.exports = require("buffer"); +module.exports = require("http"); /***/ }), -/* 283 */ +/* 273 */ +/***/ (function(module, exports) { + +module.exports = require("https"); + +/***/ }), +/* 274 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const EE = __webpack_require__(137) -const Yallist = __webpack_require__(284) -const EOF = Symbol('EOF') -const MAYBE_EMIT_END = Symbol('maybeEmitEnd') -const EMITTED_END = Symbol('emittedEnd') -const CLOSED = Symbol('closed') -const READ = Symbol('read') -const FLUSH = Symbol('flush') -const doIter = process.env._MP_NO_ITERATOR_SYMBOLS_ !== '1' -const ASYNCITERATOR = doIter && Symbol.asyncIterator || Symbol('asyncIterator not implemented') -const ITERATOR = doIter && Symbol.iterator || Symbol('iterator not implemented') -const FLUSHCHUNK = Symbol('flushChunk') -const SD = __webpack_require__(286).StringDecoder -const ENCODING = Symbol('encoding') -const DECODER = Symbol('decoder') -const FLOWING = Symbol('flowing') -const RESUME = Symbol('resume') -const BUFFERLENGTH = Symbol('bufferLength') -const BUFFERPUSH = Symbol('bufferPush') -const BUFFERSHIFT = Symbol('bufferShift') -const OBJECTMODE = Symbol('objectMode') -// Buffer in node 4.x < 4.5.0 doesn't have working Buffer.from -// or Buffer.alloc, and Buffer in node 10 deprecated the ctor. -// .M, this is fine .\^/M.. -let B = Buffer -/* istanbul ignore next */ -if (!B.alloc) { - B = __webpack_require__(281).Buffer +/** + * Detect Electron renderer / nwjs process, which is node, but we should + * treat as a browser. + */ +if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { + module.exports = __webpack_require__(275); +} else { + module.exports = __webpack_require__(277); } -module.exports = class MiniPass extends EE { - constructor (options) { - super() - this[FLOWING] = false - this.pipes = new Yallist() - this.buffer = new Yallist() - this[OBJECTMODE] = options && options.objectMode || false - if (this[OBJECTMODE]) - this[ENCODING] = null - else - this[ENCODING] = options && options.encoding || null - if (this[ENCODING] === 'buffer') - this[ENCODING] = null - this[DECODER] = this[ENCODING] ? new SD(this[ENCODING]) : null - this[EOF] = false - this[EMITTED_END] = false - this[CLOSED] = false - this.writable = true - this.readable = true - this[BUFFERLENGTH] = 0 - } - get bufferLength () { return this[BUFFERLENGTH] } - get encoding () { return this[ENCODING] } - set encoding (enc) { - if (this[OBJECTMODE]) - throw new Error('cannot set encoding in objectMode') +/***/ }), +/* 275 */ +/***/ (function(module, exports, __webpack_require__) { - if (this[ENCODING] && enc !== this[ENCODING] && - (this[DECODER] && this[DECODER].lastNeed || this[BUFFERLENGTH])) - throw new Error('cannot change encoding') +"use strict"; - if (this[ENCODING] !== enc) { - this[DECODER] = enc ? new SD(enc) : null - if (this.buffer.length) - this.buffer = this.buffer.map(chunk => this[DECODER].write(chunk)) - } - this[ENCODING] = enc - } +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } - setEncoding (enc) { - this.encoding = enc - } +/* eslint-env browser */ - write (chunk, encoding, cb) { - if (this[EOF]) - throw new Error('write after end') +/** + * This is the web browser implementation of `debug()`. + */ +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = localstorage(); +/** + * Colors. + */ - if (typeof encoding === 'function') - cb = encoding, encoding = 'utf8' +exports.colors = ['#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33']; +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ +// eslint-disable-next-line complexity - if (!encoding) - encoding = 'utf8' +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { + return true; + } // Internet Explorer and Edge do not support colors. - // fast-path writing strings of same encoding to a stream with - // an empty buffer, skipping the buffer/decoder dance - if (typeof chunk === 'string' && !this[OBJECTMODE] && - // unless it is a string already ready for us to use - !(encoding === this[ENCODING] && !this[DECODER].lastNeed)) { - chunk = B.from(chunk, encoding) - } - if (B.isBuffer(chunk) && this[ENCODING]) - chunk = this[DECODER].write(chunk) + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } // Is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 - try { - return this.flowing - ? (this.emit('data', chunk), this.flowing) - : (this[BUFFERPUSH](chunk), false) - } finally { - this.emit('readable') - if (cb) - cb() - } - } - read (n) { - try { - if (this[BUFFERLENGTH] === 0 || n === 0 || n > this[BUFFERLENGTH]) - return null + return typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773 + typeof window !== 'undefined' && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker + typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/); +} +/** + * Colorize log arguments if enabled. + * + * @api public + */ - if (this[OBJECTMODE]) - n = null - if (this.buffer.length > 1 && !this[OBJECTMODE]) { - if (this.encoding) - this.buffer = new Yallist([ - Array.from(this.buffer).join('') - ]) - else - this.buffer = new Yallist([ - B.concat(Array.from(this.buffer), this[BUFFERLENGTH]) - ]) - } +function formatArgs(args) { + args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + '+' + module.exports.humanize(this.diff); - return this[READ](n || null, this.buffer.head.value) - } finally { - this[MAYBE_EMIT_END]() - } + if (!this.useColors) { + return; } - [READ] (n, chunk) { - if (n === chunk.length || n === null) - this[BUFFERSHIFT]() - else { - this.buffer.head.value = chunk.slice(n) - chunk = chunk.slice(0, n) - this[BUFFERLENGTH] -= n + var c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit'); // The final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + + var index = 0; + var lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, function (match) { + if (match === '%%') { + return; } - this.emit('data', chunk) + index++; - if (!this.buffer.length && !this[EOF]) - this.emit('drain') + if (match === '%c') { + // We only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + args.splice(lastC, 0, c); +} +/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ - return chunk - } - end (chunk, encoding, cb) { - if (typeof chunk === 'function') - cb = chunk, chunk = null - if (typeof encoding === 'function') - cb = encoding, encoding = 'utf8' - if (chunk) - this.write(chunk, encoding) - if (cb) - this.once('end', cb) - this[EOF] = true - this.writable = false - if (this.flowing) - this[MAYBE_EMIT_END]() - } +function log() { + var _console; - // don't let the internal resume be overwritten - [RESUME] () { - this[FLOWING] = true - this.emit('resume') - if (this.buffer.length) - this[FLUSH]() - else if (this[EOF]) - this[MAYBE_EMIT_END]() - else - this.emit('drain') - } + // This hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return (typeof console === "undefined" ? "undefined" : _typeof(console)) === 'object' && console.log && (_console = console).log.apply(_console, arguments); +} +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ - resume () { - return this[RESUME]() - } - pause () { - this[FLOWING] = false +function save(namespaces) { + try { + if (namespaces) { + exports.storage.setItem('debug', namespaces); + } else { + exports.storage.removeItem('debug'); + } + } catch (error) {// Swallow + // XXX (@Qix-) should we be logging these? } +} +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ - get flowing () { - return this[FLOWING] - } - [BUFFERPUSH] (chunk) { - if (this[OBJECTMODE]) - this[BUFFERLENGTH] += 1 - else - this[BUFFERLENGTH] += chunk.length - return this.buffer.push(chunk) - } +function load() { + var r; - [BUFFERSHIFT] () { - if (this.buffer.length) { - if (this[OBJECTMODE]) - this[BUFFERLENGTH] -= 1 - else - this[BUFFERLENGTH] -= this.buffer.head.value.length - } - return this.buffer.shift() - } + try { + r = exports.storage.getItem('debug'); + } catch (error) {} // Swallow + // XXX (@Qix-) should we be logging these? + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG - [FLUSH] () { - do {} while (this[FLUSHCHUNK](this[BUFFERSHIFT]())) - if (!this.buffer.length && !this[EOF]) - this.emit('drain') + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; } - [FLUSHCHUNK] (chunk) { - return chunk ? (this.emit('data', chunk), this.flowing) : false - } + return r; +} +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ - pipe (dest, opts) { - if (dest === process.stdout || dest === process.stderr) - (opts = opts || {}).end = false - const p = { dest: dest, opts: opts, ondrain: _ => this[RESUME]() } - this.pipes.push(p) - dest.on('drain', p.ondrain) - this[RESUME]() - return dest +function localstorage() { + try { + // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage; + } catch (error) {// Swallow + // XXX (@Qix-) should we be logging these? } +} - addListener (ev, fn) { - return this.on(ev, fn) - } +module.exports = __webpack_require__(276)(exports); +var formatters = module.exports.formatters; +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ - on (ev, fn) { - try { - return super.on(ev, fn) - } finally { - if (ev === 'data' && !this.pipes.length && !this.flowing) - this[RESUME]() - else if (ev === 'end' && this[EMITTED_END]) { - super.emit('end') - this.removeAllListeners('end') - } - } +formatters.j = function (v) { + try { + return JSON.stringify(v); + } catch (error) { + return '[UnexpectedJSONParseError]: ' + error.message; } +}; - get emittedEnd () { - return this[EMITTED_END] - } - [MAYBE_EMIT_END] () { - if (!this[EMITTED_END] && this.buffer.length === 0 && this[EOF]) { - this.emit('end') - this.emit('prefinish') - this.emit('finish') - if (this[CLOSED]) - this.emit('close') - } - } - emit (ev, data) { - if (ev === 'data') { - if (!data) - return +/***/ }), +/* 276 */ +/***/ (function(module, exports, __webpack_require__) { - if (this.pipes.length) - this.pipes.forEach(p => p.dest.write(data) || this.pause()) - } else if (ev === 'end') { - if (this[EMITTED_END] === true) - return +"use strict"; - this[EMITTED_END] = true - this.readable = false - if (this[DECODER]) { - data = this[DECODER].end() - if (data) { - this.pipes.forEach(p => p.dest.write(data)) - super.emit('data', data) - } - } +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ +function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = __webpack_require__(9); + Object.keys(env).forEach(function (key) { + createDebug[key] = env[key]; + }); + /** + * Active `debug` instances. + */ - this.pipes.forEach(p => { - p.dest.removeListener('drain', p.ondrain) - if (!p.opts || p.opts.end !== false) - p.dest.end() - }) - } else if (ev === 'close') { - this[CLOSED] = true - // don't emit close before 'end' and 'finish' - if (!this[EMITTED_END]) - return - } + createDebug.instances = []; + /** + * The currently active debug mode names, and names to skip. + */ - const args = new Array(arguments.length) - args[0] = ev - args[1] = data - if (arguments.length > 2) { - for (let i = 2; i < arguments.length; i++) { - args[i] = arguments[i] - } - } + createDebug.names = []; + createDebug.skips = []; + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ - try { - return super.emit.apply(this, args) - } finally { - if (ev !== 'end') - this[MAYBE_EMIT_END]() - else - this.removeAllListeners('end') + createDebug.formatters = {}; + /** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */ + + function selectColor(namespace) { + var hash = 0; + + for (var i = 0; i < namespace.length; i++) { + hash = (hash << 5) - hash + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer } - } - // const all = await stream.collect() - collect () { - return new Promise((resolve, reject) => { - const buf = [] - this.on('data', c => buf.push(c)) - this.on('end', () => resolve(buf)) - this.on('error', reject) - }) + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; } - // for await (let chunk of stream) - [ASYNCITERATOR] () { - const next = () => { - const res = this.read() - if (res !== null) - return Promise.resolve({ done: false, value: res }) + createDebug.selectColor = selectColor; + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ - if (this[EOF]) - return Promise.resolve({ done: true }) + function createDebug(namespace) { + var prevTime; - let resolve = null - let reject = null - const onerr = er => { - this.removeListener('data', ondata) - this.removeListener('end', onend) - reject(er) - } - const ondata = value => { - this.removeListener('error', onerr) - this.removeListener('end', onend) - this.pause() - resolve({ value: value, done: !!this[EOF] }) + function debug() { + // Disabled? + if (!debug.enabled) { + return; } - const onend = () => { - this.removeListener('error', onerr) - this.removeListener('data', ondata) - resolve({ done: true }) + + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; } - return new Promise((res, rej) => { - reject = rej - resolve = res - this.once('error', onerr) - this.once('end', onend) - this.once('data', ondata) - }) - } - return { next } - } + var self = debug; // Set `diff` timestamp - // for (let chunk of stream) - [ITERATOR] () { - const next = () => { - const value = this.read() - const done = value === null - return { value, done } - } - return { next } - } -} + var curr = Number(new Date()); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + args[0] = createDebug.coerce(args[0]); + if (typeof args[0] !== 'string') { + // Anything else let's inspect with %O + args.unshift('%O'); + } // Apply any `formatters` transformations -/***/ }), -/* 284 */ -/***/ (function(module, exports, __webpack_require__) { -"use strict"; + var index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, function (match, format) { + // If we encounter an escaped % then don't increase the array index + if (match === '%%') { + return match; + } -module.exports = Yallist + index++; + var formatter = createDebug.formatters[format]; -Yallist.Node = Node -Yallist.create = Yallist + if (typeof formatter === 'function') { + var val = args[index]; + match = formatter.call(self, val); // Now we need to remove `args[index]` since it's inlined in the `format` -function Yallist (list) { - var self = this - if (!(self instanceof Yallist)) { - self = new Yallist() - } + args.splice(index, 1); + index--; + } - self.tail = null - self.head = null - self.length = 0 + return match; + }); // Apply env-specific formatting (colors, etc.) - if (list && typeof list.forEach === 'function') { - list.forEach(function (item) { - self.push(item) - }) - } else if (arguments.length > 0) { - for (var i = 0, l = arguments.length; i < l; i++) { - self.push(arguments[i]) + createDebug.formatArgs.call(self, args); + var logFn = self.log || createDebug.log; + logFn.apply(self, args); } - } - - return self -} -Yallist.prototype.removeNode = function (node) { - if (node.list !== this) { - throw new Error('removing node which does not belong to this list') - } - - var next = node.next - var prev = node.prev + debug.namespace = namespace; + debug.enabled = createDebug.enabled(namespace); + debug.useColors = createDebug.useColors(); + debug.color = selectColor(namespace); + debug.destroy = destroy; + debug.extend = extend; // Debug.formatArgs = formatArgs; + // debug.rawLog = rawLog; + // env-specific initialization logic for debug instances - if (next) { - next.prev = prev - } + if (typeof createDebug.init === 'function') { + createDebug.init(debug); + } - if (prev) { - prev.next = next + createDebug.instances.push(debug); + return debug; } - if (node === this.head) { - this.head = next - } - if (node === this.tail) { - this.tail = prev - } + function destroy() { + var index = createDebug.instances.indexOf(this); - node.list.length-- - node.next = null - node.prev = null - node.list = null -} + if (index !== -1) { + createDebug.instances.splice(index, 1); + return true; + } -Yallist.prototype.unshiftNode = function (node) { - if (node === this.head) { - return + return false; } - if (node.list) { - node.list.removeNode(node) + function extend(namespace, delimiter) { + return createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); } + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ - var head = this.head - node.list = this - node.next = head - if (head) { - head.prev = node - } - this.head = node - if (!this.tail) { - this.tail = node - } - this.length++ -} + function enable(namespaces) { + createDebug.save(namespaces); + createDebug.names = []; + createDebug.skips = []; + var i; + var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + var len = split.length; -Yallist.prototype.pushNode = function (node) { - if (node === this.tail) { - return - } + for (i = 0; i < len; i++) { + if (!split[i]) { + // ignore empty strings + continue; + } - if (node.list) { - node.list.removeNode(node) - } + namespaces = split[i].replace(/\*/g, '.*?'); - var tail = this.tail - node.list = this - node.prev = tail - if (tail) { - tail.next = node - } + if (namespaces[0] === '-') { + createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + createDebug.names.push(new RegExp('^' + namespaces + '$')); + } + } - this.tail = node - if (!this.head) { - this.head = node + for (i = 0; i < createDebug.instances.length; i++) { + var instance = createDebug.instances[i]; + instance.enabled = createDebug.enabled(instance.namespace); + } } - this.length++ -} + /** + * Disable debug output. + * + * @api public + */ -Yallist.prototype.push = function () { - for (var i = 0, l = arguments.length; i < l; i++) { - push(this, arguments[i]) - } - return this.length -} -Yallist.prototype.unshift = function () { - for (var i = 0, l = arguments.length; i < l; i++) { - unshift(this, arguments[i]) + function disable() { + createDebug.enable(''); } - return this.length -} + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ -Yallist.prototype.pop = function () { - if (!this.tail) { - return undefined - } - var res = this.tail.value - this.tail = this.tail.prev - if (this.tail) { - this.tail.next = null - } else { - this.head = null - } - this.length-- - return res -} + function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } -Yallist.prototype.shift = function () { - if (!this.head) { - return undefined - } + var i; + var len; - var res = this.head.value - this.head = this.head.next - if (this.head) { - this.head.prev = null - } else { - this.tail = null - } - this.length-- - return res -} + for (i = 0, len = createDebug.skips.length; i < len; i++) { + if (createDebug.skips[i].test(name)) { + return false; + } + } -Yallist.prototype.forEach = function (fn, thisp) { - thisp = thisp || this - for (var walker = this.head, i = 0; walker !== null; i++) { - fn.call(thisp, walker.value, i, this) - walker = walker.next - } -} + for (i = 0, len = createDebug.names.length; i < len; i++) { + if (createDebug.names[i].test(name)) { + return true; + } + } -Yallist.prototype.forEachReverse = function (fn, thisp) { - thisp = thisp || this - for (var walker = this.tail, i = this.length - 1; walker !== null; i--) { - fn.call(thisp, walker.value, i, this) - walker = walker.prev + return false; } -} + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ -Yallist.prototype.get = function (n) { - for (var i = 0, walker = this.head; walker !== null && i < n; i++) { - // abort out of the list early if we hit a cycle - walker = walker.next - } - if (i === n && walker !== null) { - return walker.value - } -} -Yallist.prototype.getReverse = function (n) { - for (var i = 0, walker = this.tail; walker !== null && i < n; i++) { - // abort out of the list early if we hit a cycle - walker = walker.prev - } - if (i === n && walker !== null) { - return walker.value - } -} + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } -Yallist.prototype.map = function (fn, thisp) { - thisp = thisp || this - var res = new Yallist() - for (var walker = this.head; walker !== null;) { - res.push(fn.call(thisp, walker.value, this)) - walker = walker.next + return val; } - return res -} -Yallist.prototype.mapReverse = function (fn, thisp) { - thisp = thisp || this - var res = new Yallist() - for (var walker = this.tail; walker !== null;) { - res.push(fn.call(thisp, walker.value, this)) - walker = walker.prev - } - return res + createDebug.enable(createDebug.load()); + return createDebug; } -Yallist.prototype.reduce = function (fn, initial) { - var acc - var walker = this.head - if (arguments.length > 1) { - acc = initial - } else if (this.head) { - walker = this.head.next - acc = this.head.value - } else { - throw new TypeError('Reduce of empty list with no initial value') - } +module.exports = setup; - for (var i = 0; walker !== null; i++) { - acc = fn(acc, walker.value, i) - walker = walker.next + + +/***/ }), +/* 277 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/** + * Module dependencies. + */ +var tty = __webpack_require__(11); + +var util = __webpack_require__(12); +/** + * This is the Node.js implementation of `debug()`. + */ + + +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +/** + * Colors. + */ + +exports.colors = [6, 2, 3, 4, 5, 1]; + +try { + // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) + // eslint-disable-next-line import/no-extraneous-dependencies + var supportsColor = __webpack_require__(13); + + if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { + exports.colors = [20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68, 69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134, 135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 214, 215, 220, 221]; } +} catch (error) {} // Swallow - we only care if `supports-color` is available; it doesn't have to be. - return acc -} +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ -Yallist.prototype.reduceReverse = function (fn, initial) { - var acc - var walker = this.tail - if (arguments.length > 1) { - acc = initial - } else if (this.tail) { - walker = this.tail.prev - acc = this.tail.value + +exports.inspectOpts = Object.keys(process.env).filter(function (key) { + return /^debug_/i.test(key); +}).reduce(function (obj, key) { + // Camel-case + var prop = key.substring(6).toLowerCase().replace(/_([a-z])/g, function (_, k) { + return k.toUpperCase(); + }); // Coerce string value into JS value + + var val = process.env[key]; + + if (/^(yes|on|true|enabled)$/i.test(val)) { + val = true; + } else if (/^(no|off|false|disabled)$/i.test(val)) { + val = false; + } else if (val === 'null') { + val = null; } else { - throw new TypeError('Reduce of empty list with no initial value') + val = Number(val); } - for (var i = this.length - 1; walker !== null; i--) { - acc = fn(acc, walker.value, i) - walker = walker.prev - } + obj[prop] = val; + return obj; +}, {}); +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ - return acc +function useColors() { + return 'colors' in exports.inspectOpts ? Boolean(exports.inspectOpts.colors) : tty.isatty(process.stderr.fd); } +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ -Yallist.prototype.toArray = function () { - var arr = new Array(this.length) - for (var i = 0, walker = this.head; walker !== null; i++) { - arr[i] = walker.value - walker = walker.next - } - return arr -} -Yallist.prototype.toArrayReverse = function () { - var arr = new Array(this.length) - for (var i = 0, walker = this.tail; walker !== null; i++) { - arr[i] = walker.value - walker = walker.prev +function formatArgs(args) { + var name = this.namespace, + useColors = this.useColors; + + if (useColors) { + var c = this.color; + var colorCode = "\x1B[3" + (c < 8 ? c : '8;5;' + c); + var prefix = " ".concat(colorCode, ";1m").concat(name, " \x1B[0m"); + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + "\x1B[0m"); + } else { + args[0] = getDate() + name + ' ' + args[0]; } - return arr } -Yallist.prototype.slice = function (from, to) { - to = to || this.length - if (to < 0) { - to += this.length - } - from = from || 0 - if (from < 0) { - from += this.length - } - var ret = new Yallist() - if (to < from || to < 0) { - return ret - } - if (from < 0) { - from = 0 - } - if (to > this.length) { - to = this.length - } - for (var i = 0, walker = this.head; walker !== null && i < from; i++) { - walker = walker.next - } - for (; walker !== null && i < to; i++, walker = walker.next) { - ret.push(walker.value) +function getDate() { + if (exports.inspectOpts.hideDate) { + return ''; } - return ret + + return new Date().toISOString() + ' '; } +/** + * Invokes `util.format()` with the specified arguments and writes to stderr. + */ -Yallist.prototype.sliceReverse = function (from, to) { - to = to || this.length - if (to < 0) { - to += this.length - } - from = from || 0 - if (from < 0) { - from += this.length - } - var ret = new Yallist() - if (to < from || to < 0) { - return ret - } - if (from < 0) { - from = 0 - } - if (to > this.length) { - to = this.length - } - for (var i = this.length, walker = this.tail; walker !== null && i > to; i--) { - walker = walker.prev - } - for (; walker !== null && i > from; i--, walker = walker.prev) { - ret.push(walker.value) - } - return ret + +function log() { + return process.stderr.write(util.format.apply(util, arguments) + '\n'); } +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ -Yallist.prototype.reverse = function () { - var head = this.head - var tail = this.tail - for (var walker = head; walker !== null; walker = walker.prev) { - var p = walker.prev - walker.prev = walker.next - walker.next = p + +function save(namespaces) { + if (namespaces) { + process.env.DEBUG = namespaces; + } else { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; } - this.head = tail - this.tail = head - return this } +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ -function push (self, item) { - self.tail = new Node(item, self.tail, null, self) - if (!self.head) { - self.head = self.tail - } - self.length++ + +function load() { + return process.env.DEBUG; } +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ -function unshift (self, item) { - self.head = new Node(item, null, self.head, self) - if (!self.tail) { - self.tail = self.head + +function init(debug) { + debug.inspectOpts = {}; + var keys = Object.keys(exports.inspectOpts); + + for (var i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; } - self.length++ } -function Node (value, prev, next, list) { - if (!(this instanceof Node)) { - return new Node(value, prev, next, list) - } +module.exports = __webpack_require__(276)(exports); +var formatters = module.exports.formatters; +/** + * Map %o to `util.inspect()`, all on a single line. + */ - this.list = list - this.value = value +formatters.o = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts).replace(/\s*\n\s*/g, ' '); +}; +/** + * Map %O to `util.inspect()`, allowing multiple lines if needed. + */ - if (prev) { - prev.next = this - this.prev = prev - } else { - this.prev = null - } - if (next) { - next.prev = this - this.next = next - } else { - this.next = null - } -} +formatters.O = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); +}; -try { - // add if support for Symbol.iterator is present - __webpack_require__(285)(Yallist) -} catch (er) {} /***/ }), -/* 285 */ +/* 278 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = function (Yallist) { - Yallist.prototype[Symbol.iterator] = function* () { - for (let walker = this.head; walker; walker = walker.next) { - yield walker.value - } - } -} +// high-level commands +exports.c = exports.create = __webpack_require__(279) +exports.r = exports.replace = __webpack_require__(303) +exports.t = exports.list = __webpack_require__(301) +exports.u = exports.update = __webpack_require__(304) +exports.x = exports.extract = __webpack_require__(305) -/***/ }), -/* 286 */ -/***/ (function(module, exports) { +// classes +exports.Pack = __webpack_require__(281) +exports.Unpack = __webpack_require__(306) +exports.Parse = __webpack_require__(302) +exports.ReadEntry = __webpack_require__(291) +exports.WriteEntry = __webpack_require__(293) +exports.Header = __webpack_require__(295) +exports.Pax = __webpack_require__(294) +exports.types = __webpack_require__(292) -module.exports = require("string_decoder"); /***/ }), -/* 287 */ +/* 279 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const assert = __webpack_require__(46) -const Buffer = __webpack_require__(282).Buffer -const realZlib = __webpack_require__(82) +// tar -c +const hlo = __webpack_require__(280) -const constants = exports.constants = __webpack_require__(288) -const MiniPass = __webpack_require__(283) +const Pack = __webpack_require__(281) +const fs = __webpack_require__(4) +const fsm = __webpack_require__(300) +const t = __webpack_require__(301) +const path = __webpack_require__(20) -const OriginalBufferConcat = Buffer.concat +const c = module.exports = (opt_, files, cb) => { + if (typeof files === 'function') + cb = files -class ZlibError extends Error { - constructor (msg, errno) { - super('zlib: ' + msg) - this.errno = errno - this.code = codes.get(errno) - } + if (Array.isArray(opt_)) + files = opt_, opt_ = {} - get name () { - return 'ZlibError' - } -} + if (!files || !Array.isArray(files) || !files.length) + throw new TypeError('no files or directories specified') -// translation table for return codes. -const codes = new Map([ - [constants.Z_OK, 'Z_OK'], - [constants.Z_STREAM_END, 'Z_STREAM_END'], - [constants.Z_NEED_DICT, 'Z_NEED_DICT'], - [constants.Z_ERRNO, 'Z_ERRNO'], - [constants.Z_STREAM_ERROR, 'Z_STREAM_ERROR'], - [constants.Z_DATA_ERROR, 'Z_DATA_ERROR'], - [constants.Z_MEM_ERROR, 'Z_MEM_ERROR'], - [constants.Z_BUF_ERROR, 'Z_BUF_ERROR'], - [constants.Z_VERSION_ERROR, 'Z_VERSION_ERROR'] -]) + files = Array.from(files) -const validFlushFlags = new Set([ - constants.Z_NO_FLUSH, - constants.Z_PARTIAL_FLUSH, - constants.Z_SYNC_FLUSH, - constants.Z_FULL_FLUSH, - constants.Z_FINISH, - constants.Z_BLOCK -]) + const opt = hlo(opt_) -const strategies = new Set([ - constants.Z_FILTERED, - constants.Z_HUFFMAN_ONLY, - constants.Z_RLE, - constants.Z_FIXED, - constants.Z_DEFAULT_STRATEGY -]) + if (opt.sync && typeof cb === 'function') + throw new TypeError('callback not supported for sync tar functions') -// the Zlib class they all inherit from -// This thing manages the queue of requests, and returns -// true or false if there is anything in the queue when -// you call the .write() method. -const _opts = Symbol('opts') -const _flushFlag = Symbol('flushFlag') -const _finishFlush = Symbol('finishFlush') -const _handle = Symbol('handle') -const _onError = Symbol('onError') -const _level = Symbol('level') -const _strategy = Symbol('strategy') -const _ended = Symbol('ended') + if (!opt.file && typeof cb === 'function') + throw new TypeError('callback only supported with file option') -class Zlib extends MiniPass { - constructor (opts, mode) { - super(opts) - this[_ended] = false - this[_opts] = opts = opts || {} - if (opts.flush && !validFlushFlags.has(opts.flush)) { - throw new TypeError('Invalid flush flag: ' + opts.flush) - } - if (opts.finishFlush && !validFlushFlags.has(opts.finishFlush)) { - throw new TypeError('Invalid flush flag: ' + opts.finishFlush) - } + return opt.file && opt.sync ? createFileSync(opt, files) + : opt.file ? createFile(opt, files, cb) + : opt.sync ? createSync(opt, files) + : create(opt, files) +} - this[_flushFlag] = opts.flush || constants.Z_NO_FLUSH - this[_finishFlush] = typeof opts.finishFlush !== 'undefined' ? - opts.finishFlush : constants.Z_FINISH +const createFileSync = (opt, files) => { + const p = new Pack.Sync(opt) + const stream = new fsm.WriteStreamSync(opt.file, { + mode: opt.mode || 0o666 + }) + p.pipe(stream) + addFilesSync(p, files) +} - if (opts.chunkSize) { - if (opts.chunkSize < constants.Z_MIN_CHUNK) { - throw new RangeError('Invalid chunk size: ' + opts.chunkSize) - } - } +const createFile = (opt, files, cb) => { + const p = new Pack(opt) + const stream = new fsm.WriteStream(opt.file, { + mode: opt.mode || 0o666 + }) + p.pipe(stream) - if (opts.windowBits) { - if (opts.windowBits < constants.Z_MIN_WINDOWBITS || - opts.windowBits > constants.Z_MAX_WINDOWBITS) { - throw new RangeError('Invalid windowBits: ' + opts.windowBits) - } - } + const promise = new Promise((res, rej) => { + stream.on('error', rej) + stream.on('close', res) + p.on('error', rej) + }) - if (opts.level) { - if (opts.level < constants.Z_MIN_LEVEL || - opts.level > constants.Z_MAX_LEVEL) { - throw new RangeError('Invalid compression level: ' + opts.level) - } - } + addFilesAsync(p, files) - if (opts.memLevel) { - if (opts.memLevel < constants.Z_MIN_MEMLEVEL || - opts.memLevel > constants.Z_MAX_MEMLEVEL) { - throw new RangeError('Invalid memLevel: ' + opts.memLevel) - } - } + return cb ? promise.then(cb, cb) : promise +} - if (opts.strategy && !(strategies.has(opts.strategy))) - throw new TypeError('Invalid strategy: ' + opts.strategy) +const addFilesSync = (p, files) => { + files.forEach(file => { + if (file.charAt(0) === '@') + t({ + file: path.resolve(p.cwd, file.substr(1)), + sync: true, + noResume: true, + onentry: entry => p.add(entry) + }) + else + p.add(file) + }) + p.end() +} - if (opts.dictionary) { - if (!(opts.dictionary instanceof Buffer)) { - throw new TypeError('Invalid dictionary: it should be a Buffer instance') - } - } +const addFilesAsync = (p, files) => { + while (files.length) { + const file = files.shift() + if (file.charAt(0) === '@') + return t({ + file: path.resolve(p.cwd, file.substr(1)), + noResume: true, + onentry: entry => p.add(entry) + }).then(_ => addFilesAsync(p, files)) + else + p.add(file) + } + p.end() +} - this[_handle] = new realZlib[mode](opts) +const createSync = (opt, files) => { + const p = new Pack.Sync(opt) + addFilesSync(p, files) + return p +} - this[_onError] = (err) => { - // there is no way to cleanly recover. - // continuing only obscures problems. - this.close() +const create = (opt, files) => { + const p = new Pack(opt) + addFilesAsync(p, files) + return p +} - const error = new ZlibError(err.message, err.errno) - this.emit('error', error) - } - this[_handle].on('error', this[_onError]) - const level = typeof opts.level === 'number' ? opts.level - : constants.Z_DEFAULT_COMPRESSION +/***/ }), +/* 280 */ +/***/ (function(module, exports, __webpack_require__) { - var strategy = typeof opts.strategy === 'number' ? opts.strategy - : constants.Z_DEFAULT_STRATEGY +"use strict"; - // API changed in node v9 - /* istanbul ignore next */ - this[_level] = level - this[_strategy] = strategy +// turn tar(1) style args like `C` into the more verbose things like `cwd` - this.once('end', this.close) - } +const argmap = new Map([ + ['C', 'cwd'], + ['f', 'file'], + ['z', 'gzip'], + ['P', 'preservePaths'], + ['U', 'unlink'], + ['strip-components', 'strip'], + ['stripComponents', 'strip'], + ['keep-newer', 'newer'], + ['keepNewer', 'newer'], + ['keep-newer-files', 'newer'], + ['keepNewerFiles', 'newer'], + ['k', 'keep'], + ['keep-existing', 'keep'], + ['keepExisting', 'keep'], + ['m', 'noMtime'], + ['no-mtime', 'noMtime'], + ['p', 'preserveOwner'], + ['L', 'follow'], + ['h', 'follow'] +]) - close () { - if (this[_handle]) { - this[_handle].close() - this[_handle] = null - this.emit('close') - } - } +const parse = module.exports = opt => opt ? Object.keys(opt).map(k => [ + argmap.has(k) ? argmap.get(k) : k, opt[k] +]).reduce((set, kv) => (set[kv[0]] = kv[1], set), Object.create(null)) : {} - params (level, strategy) { - if (!this[_handle]) - throw new Error('cannot switch params when binding is closed') - // no way to test this without also not supporting params at all - /* istanbul ignore if */ - if (!this[_handle].params) - throw new Error('not supported in this implementation') +/***/ }), +/* 281 */ +/***/ (function(module, exports, __webpack_require__) { - if (level < constants.Z_MIN_LEVEL || - level > constants.Z_MAX_LEVEL) { - throw new RangeError('Invalid compression level: ' + level) - } +"use strict"; - if (!(strategies.has(strategy))) - throw new TypeError('Invalid strategy: ' + strategy) - if (this[_level] !== level || this[_strategy] !== strategy) { - this.flush(constants.Z_SYNC_FLUSH) - assert(this[_handle], 'zlib binding closed') - // .params() calls .flush(), but the latter is always async in the - // core zlib. We override .flush() temporarily to intercept that and - // flush synchronously. - const origFlush = this[_handle].flush - this[_handle].flush = (flushFlag, cb) => { - this[_handle].flush = origFlush - this.flush(flushFlag) - cb() - } - this[_handle].params(level, strategy) - /* istanbul ignore else */ - if (this[_handle]) { - this[_level] = level - this[_strategy] = strategy - } - } - } +const Buffer = __webpack_require__(282) - reset () { - assert(this[_handle], 'zlib binding closed') - return this[_handle].reset() +// A readable tar stream creator +// Technically, this is a transform stream that you write paths into, +// and tar format comes out of. +// The `add()` method is like `write()` but returns this, +// and end() return `this` as well, so you can +// do `new Pack(opt).add('files').add('dir').end().pipe(output) +// You could also do something like: +// streamOfPaths().pipe(new Pack()).pipe(new fs.WriteStream('out.tar')) + +class PackJob { + constructor (path, absolute) { + this.path = path || './' + this.absolute = absolute + this.entry = null + this.stat = null + this.readdir = null + this.pending = false + this.ignore = false + this.piped = false } +} - flush (kind) { - if (kind === undefined) - kind = constants.Z_FULL_FLUSH +const MiniPass = __webpack_require__(285) +const zlib = __webpack_require__(289) +const ReadEntry = __webpack_require__(291) +const WriteEntry = __webpack_require__(293) +const WriteEntrySync = WriteEntry.Sync +const WriteEntryTar = WriteEntry.Tar +const Yallist = __webpack_require__(286) +const EOF = Buffer.alloc(1024) +const ONSTAT = Symbol('onStat') +const ENDED = Symbol('ended') +const QUEUE = Symbol('queue') +const CURRENT = Symbol('current') +const PROCESS = Symbol('process') +const PROCESSING = Symbol('processing') +const PROCESSJOB = Symbol('processJob') +const JOBS = Symbol('jobs') +const JOBDONE = Symbol('jobDone') +const ADDFSENTRY = Symbol('addFSEntry') +const ADDTARENTRY = Symbol('addTarEntry') +const STAT = Symbol('stat') +const READDIR = Symbol('readdir') +const ONREADDIR = Symbol('onreaddir') +const PIPE = Symbol('pipe') +const ENTRY = Symbol('entry') +const ENTRYOPT = Symbol('entryOpt') +const WRITEENTRYCLASS = Symbol('writeEntryClass') +const WRITE = Symbol('write') +const ONDRAIN = Symbol('ondrain') - if (this.ended) - return +const fs = __webpack_require__(4) +const path = __webpack_require__(20) +const warner = __webpack_require__(297) - const flushFlag = this[_flushFlag] - this[_flushFlag] = kind - this.write(Buffer.alloc(0)) - this[_flushFlag] = flushFlag +const Pack = warner(class Pack extends MiniPass { + constructor (opt) { + super(opt) + opt = opt || Object.create(null) + this.opt = opt + this.cwd = opt.cwd || process.cwd() + this.maxReadSize = opt.maxReadSize + this.preservePaths = !!opt.preservePaths + this.strict = !!opt.strict + this.noPax = !!opt.noPax + this.prefix = (opt.prefix || '').replace(/(\\|\/)+$/, '') + this.linkCache = opt.linkCache || new Map() + this.statCache = opt.statCache || new Map() + this.readdirCache = opt.readdirCache || new Map() + + this[WRITEENTRYCLASS] = WriteEntry + if (typeof opt.onwarn === 'function') + this.on('warn', opt.onwarn) + + this.zip = null + if (opt.gzip) { + if (typeof opt.gzip !== 'object') + opt.gzip = {} + this.zip = new zlib.Gzip(opt.gzip) + this.zip.on('data', chunk => super.write(chunk)) + this.zip.on('end', _ => super.end()) + this.zip.on('drain', _ => this[ONDRAIN]()) + this.on('resume', _ => this.zip.resume()) + } else + this.on('drain', this[ONDRAIN]) + + this.portable = !!opt.portable + this.noDirRecurse = !!opt.noDirRecurse + this.follow = !!opt.follow + this.noMtime = !!opt.noMtime + this.mtime = opt.mtime || null + + this.filter = typeof opt.filter === 'function' ? opt.filter : _ => true + + this[QUEUE] = new Yallist + this[JOBS] = 0 + this.jobs = +opt.jobs || 4 + this[PROCESSING] = false + this[ENDED] = false } - end (chunk, encoding, cb) { - if (chunk) - this.write(chunk, encoding) - this.flush(this[_finishFlush]) - this[_ended] = true - return super.end(null, null, cb) + [WRITE] (chunk) { + return super.write(chunk) } - get ended () { - return this[_ended] + add (path) { + this.write(path) + return this } - write (chunk, encoding, cb) { - // process the chunk using the sync process - // then super.write() all the outputted chunks - if (typeof encoding === 'function') - cb = encoding, encoding = 'utf8' + end (path) { + if (path) + this.write(path) + this[ENDED] = true + this[PROCESS]() + return this + } - if (typeof chunk === 'string') - chunk = Buffer.from(chunk, encoding) + write (path) { + if (this[ENDED]) + throw new Error('write after end') - assert(this[_handle], 'zlib binding closed') + if (path instanceof ReadEntry) + this[ADDTARENTRY](path) + else + this[ADDFSENTRY](path) + return this.flowing + } - // _processChunk tries to .close() the native handle after it's done, so we - // intercept that by temporarily making it a no-op. - const nativeHandle = this[_handle]._handle - const originalNativeClose = nativeHandle.close - nativeHandle.close = () => {} - const originalClose = this[_handle].close - this[_handle].close = () => {} - // It also calls `Buffer.concat()` at the end, which may be convenient - // for some, but which we are not interested in as it slows us down. - Buffer.concat = (args) => args - let result - try { - result = this[_handle]._processChunk(chunk, this[_flushFlag]) - } catch (err) { - this[_onError](err) - } finally { - Buffer.concat = OriginalBufferConcat - if (this[_handle]) { - // Core zlib resets `_handle` to null after attempting to close the - // native handle. Our no-op handler prevented actual closure, but we - // need to restore the `._handle` property. - this[_handle]._handle = nativeHandle - nativeHandle.close = originalNativeClose - this[_handle].close = originalClose - // `_processChunk()` adds an 'error' listener. If we don't remove it - // after each call, these handlers start piling up. - this[_handle].removeAllListeners('error') - } - } + [ADDTARENTRY] (p) { + const absolute = path.resolve(this.cwd, p.path) + if (this.prefix) + p.path = this.prefix + '/' + p.path.replace(/^\.(\/+|$)/, '') - let writeReturn - if (result) { - if (Array.isArray(result) && result.length > 0) { - // The first buffer is always `handle._outBuffer`, which would be - // re-used for later invocations; so, we always have to copy that one. - writeReturn = super.write(Buffer.from(result[0])) - for (let i = 1; i < result.length; i++) { - writeReturn = super.write(result[i]) - } - } else { - writeReturn = super.write(Buffer.from(result)) - } + // in this case, we don't have to wait for the stat + if (!this.filter(p.path, p)) + p.resume() + else { + const job = new PackJob(p.path, absolute, false) + job.entry = new WriteEntryTar(p, this[ENTRYOPT](job)) + job.entry.on('end', _ => this[JOBDONE](job)) + this[JOBS] += 1 + this[QUEUE].push(job) } - if (cb) - cb() - return writeReturn + this[PROCESS]() } -} -// minimal 2-byte header -class Deflate extends Zlib { - constructor (opts) { - super(opts, 'Deflate') - } -} + [ADDFSENTRY] (p) { + const absolute = path.resolve(this.cwd, p) + if (this.prefix) + p = this.prefix + '/' + p.replace(/^\.(\/+|$)/, '') -class Inflate extends Zlib { - constructor (opts) { - super(opts, 'Inflate') + this[QUEUE].push(new PackJob(p, absolute)) + this[PROCESS]() } -} -// gzip - bigger header, same deflate compression -class Gzip extends Zlib { - constructor (opts) { - super(opts, 'Gzip') + [STAT] (job) { + job.pending = true + this[JOBS] += 1 + const stat = this.follow ? 'stat' : 'lstat' + fs[stat](job.absolute, (er, stat) => { + job.pending = false + this[JOBS] -= 1 + if (er) + this.emit('error', er) + else + this[ONSTAT](job, stat) + }) } -} -class Gunzip extends Zlib { - constructor (opts) { - super(opts, 'Gunzip') - } -} + [ONSTAT] (job, stat) { + this.statCache.set(job.absolute, stat) + job.stat = stat -// raw - no header -class DeflateRaw extends Zlib { - constructor (opts) { - super(opts, 'DeflateRaw') + // now we have the stat, we can filter it. + if (!this.filter(job.path, stat)) + job.ignore = true + + this[PROCESS]() } -} -class InflateRaw extends Zlib { - constructor (opts) { - super(opts, 'InflateRaw') + [READDIR] (job) { + job.pending = true + this[JOBS] += 1 + fs.readdir(job.absolute, (er, entries) => { + job.pending = false + this[JOBS] -= 1 + if (er) + return this.emit('error', er) + this[ONREADDIR](job, entries) + }) } -} -// auto-detect header. -class Unzip extends Zlib { - constructor (opts) { - super(opts, 'Unzip') + [ONREADDIR] (job, entries) { + this.readdirCache.set(job.absolute, entries) + job.readdir = entries + this[PROCESS]() } -} -exports.Deflate = Deflate -exports.Inflate = Inflate -exports.Gzip = Gzip -exports.Gunzip = Gunzip -exports.DeflateRaw = DeflateRaw -exports.InflateRaw = InflateRaw -exports.Unzip = Unzip + [PROCESS] () { + if (this[PROCESSING]) + return + this[PROCESSING] = true + for (let w = this[QUEUE].head; + w !== null && this[JOBS] < this.jobs; + w = w.next) { + this[PROCESSJOB](w.value) + if (w.value.ignore) { + const p = w.next + this[QUEUE].removeNode(w) + w.next = p + } + } -/***/ }), -/* 288 */ -/***/ (function(module, exports) { + this[PROCESSING] = false -module.exports = Object.freeze({ - Z_NO_FLUSH: 0, - Z_PARTIAL_FLUSH: 1, - Z_SYNC_FLUSH: 2, - Z_FULL_FLUSH: 3, - Z_FINISH: 4, - Z_BLOCK: 5, - Z_OK: 0, - Z_STREAM_END: 1, - Z_NEED_DICT: 2, - Z_ERRNO: -1, - Z_STREAM_ERROR: -2, - Z_DATA_ERROR: -3, - Z_MEM_ERROR: -4, - Z_BUF_ERROR: -5, - Z_VERSION_ERROR: -6, - Z_NO_COMPRESSION: 0, - Z_BEST_SPEED: 1, - Z_BEST_COMPRESSION: 9, - Z_DEFAULT_COMPRESSION: -1, - Z_FILTERED: 1, - Z_HUFFMAN_ONLY: 2, - Z_RLE: 3, - Z_FIXED: 4, - Z_DEFAULT_STRATEGY: 0, - ZLIB_VERNUM: 4736, - DEFLATE: 1, - INFLATE: 2, - GZIP: 3, - GUNZIP: 4, - DEFLATERAW: 5, - INFLATERAW: 6, - UNZIP: 7, - Z_MIN_WINDOWBITS: 8, - Z_MAX_WINDOWBITS: 15, - Z_DEFAULT_WINDOWBITS: 15, - Z_MIN_CHUNK: 64, - Z_MAX_CHUNK: Infinity, - Z_DEFAULT_CHUNK: 16384, - Z_MIN_MEMLEVEL: 1, - Z_MAX_MEMLEVEL: 9, - Z_DEFAULT_MEMLEVEL: 8, - Z_MIN_LEVEL: -1, - Z_MAX_LEVEL: 9, - Z_DEFAULT_LEVEL: -1 -}) + if (this[ENDED] && !this[QUEUE].length && this[JOBS] === 0) { + if (this.zip) + this.zip.end(EOF) + else { + super.write(EOF) + super.end() + } + } + } + get [CURRENT] () { + return this[QUEUE] && this[QUEUE].head && this[QUEUE].head.value + } -/***/ }), -/* 289 */ -/***/ (function(module, exports, __webpack_require__) { + [JOBDONE] (job) { + this[QUEUE].shift() + this[JOBS] -= 1 + this[PROCESS]() + } -"use strict"; + [PROCESSJOB] (job) { + if (job.pending) + return -const types = __webpack_require__(290) -const MiniPass = __webpack_require__(283) + if (job.entry) { + if (job === this[CURRENT] && !job.piped) + this[PIPE](job) + return + } -const SLURP = Symbol('slurp') -module.exports = class ReadEntry extends MiniPass { - constructor (header, ex, gex) { - super() - this.extended = ex - this.globalExtended = gex - this.header = header - this.startBlockSize = 512 * Math.ceil(header.size / 512) - this.blockRemain = this.startBlockSize - this.remain = header.size - this.type = header.type - this.meta = false - this.ignore = false - switch (this.type) { - case 'File': - case 'OldFile': - case 'Link': - case 'SymbolicLink': - case 'CharacterDevice': - case 'BlockDevice': - case 'Directory': - case 'FIFO': - case 'ContiguousFile': - case 'GNUDumpDir': - break + if (!job.stat) { + if (this.statCache.has(job.absolute)) + this[ONSTAT](job, this.statCache.get(job.absolute)) + else + this[STAT](job) + } + if (!job.stat) + return - case 'NextFileHasLongLinkpath': - case 'NextFileHasLongPath': - case 'OldGnuLongPath': - case 'GlobalExtendedHeader': - case 'ExtendedHeader': - case 'OldExtendedHeader': - this.meta = true - break + // filtered out! + if (job.ignore) + return - // NOTE: gnutar and bsdtar treat unrecognized types as 'File' - // it may be worth doing the same, but with a warning. - default: - this.ignore = true + if (!this.noDirRecurse && job.stat.isDirectory() && !job.readdir) { + if (this.readdirCache.has(job.absolute)) + this[ONREADDIR](job, this.readdirCache.get(job.absolute)) + else + this[READDIR](job) + if (!job.readdir) + return } - this.path = header.path - this.mode = header.mode - if (this.mode) - this.mode = this.mode & 0o7777 - this.uid = header.uid - this.gid = header.gid - this.uname = header.uname - this.gname = header.gname - this.size = header.size - this.mtime = header.mtime - this.atime = header.atime - this.ctime = header.ctime - this.linkpath = header.linkpath - this.uname = header.uname - this.gname = header.gname + // we know it doesn't have an entry, because that got checked above + job.entry = this[ENTRY](job) + if (!job.entry) { + job.ignore = true + return + } - if (ex) this[SLURP](ex) - if (gex) this[SLURP](gex, true) + if (job === this[CURRENT] && !job.piped) + this[PIPE](job) } - write (data) { - const writeLen = data.length - if (writeLen > this.blockRemain) - throw new Error('writing more to entry than is appropriate') + [ENTRYOPT] (job) { + return { + onwarn: (msg, data) => { + this.warn(msg, data) + }, + noPax: this.noPax, + cwd: this.cwd, + absolute: job.absolute, + preservePaths: this.preservePaths, + maxReadSize: this.maxReadSize, + strict: this.strict, + portable: this.portable, + linkCache: this.linkCache, + statCache: this.statCache, + noMtime: this.noMtime, + mtime: this.mtime + } + } - const r = this.remain - const br = this.blockRemain - this.remain = Math.max(0, r - writeLen) - this.blockRemain = Math.max(0, br - writeLen) - if (this.ignore) - return true + [ENTRY] (job) { + this[JOBS] += 1 + try { + return new this[WRITEENTRYCLASS](job.path, this[ENTRYOPT](job)) + .on('end', () => this[JOBDONE](job)) + .on('error', er => this.emit('error', er)) + } catch (er) { + this.emit('error', er) + } + } - if (r >= writeLen) - return super.write(data) + [ONDRAIN] () { + if (this[CURRENT] && this[CURRENT].entry) + this[CURRENT].entry.resume() + } - // r < writeLen - return super.write(data.slice(0, r)) + // like .pipe() but using super, because our write() is special + [PIPE] (job) { + job.piped = true + + if (job.readdir) + job.readdir.forEach(entry => { + const p = this.prefix ? + job.path.slice(this.prefix.length + 1) || './' + : job.path + + const base = p === './' ? '' : p.replace(/\/*$/, '/') + this[ADDFSENTRY](base + entry) + }) + + const source = job.entry + const zip = this.zip + + if (zip) + source.on('data', chunk => { + if (!zip.write(chunk)) + source.pause() + }) + else + source.on('data', chunk => { + if (!super.write(chunk)) + source.pause() + }) } - [SLURP] (ex, global) { - for (let k in ex) { - // we slurp in everything except for the path attribute in - // a global extended header, because that's weird. - if (ex[k] !== null && ex[k] !== undefined && - !(global && k === 'path')) - this[k] = ex[k] - } + pause () { + if (this.zip) + this.zip.pause() + return super.pause() } -} +}) +class PackSync extends Pack { + constructor (opt) { + super(opt) + this[WRITEENTRYCLASS] = WriteEntrySync + } -/***/ }), -/* 290 */ -/***/ (function(module, exports, __webpack_require__) { + // pause/resume are no-ops in sync streams. + pause () {} + resume () {} -"use strict"; + [STAT] (job) { + const stat = this.follow ? 'statSync' : 'lstatSync' + this[ONSTAT](job, fs[stat](job.absolute)) + } -// map types from key to human-friendly name -exports.name = new Map([ - ['0', 'File'], - // same as File - ['', 'OldFile'], - ['1', 'Link'], - ['2', 'SymbolicLink'], - // Devices and FIFOs aren't fully supported - // they are parsed, but skipped when unpacking - ['3', 'CharacterDevice'], - ['4', 'BlockDevice'], - ['5', 'Directory'], - ['6', 'FIFO'], - // same as File - ['7', 'ContiguousFile'], - // pax headers - ['g', 'GlobalExtendedHeader'], - ['x', 'ExtendedHeader'], - // vendor-specific stuff - // skip - ['A', 'SolarisACL'], - // like 5, but with data, which should be skipped - ['D', 'GNUDumpDir'], - // metadata only, skip - ['I', 'Inode'], - // data = link path of next file - ['K', 'NextFileHasLongLinkpath'], - // data = path of next file - ['L', 'NextFileHasLongPath'], - // skip - ['M', 'ContinuationFile'], - // like L - ['N', 'OldGnuLongPath'], - // skip - ['S', 'SparseFile'], - // skip - ['V', 'TapeVolumeHeader'], - // like x - ['X', 'OldExtendedHeader'] -]) + [READDIR] (job, stat) { + this[ONREADDIR](job, fs.readdirSync(job.absolute)) + } -// map the other direction -exports.code = new Map(Array.from(exports.name).map(kv => [kv[1], kv[0]])) + // gotta get it all in this tick + [PIPE] (job) { + const source = job.entry + const zip = this.zip + + if (job.readdir) + job.readdir.forEach(entry => { + const p = this.prefix ? + job.path.slice(this.prefix.length + 1) || './' + : job.path + + const base = p === './' ? '' : p.replace(/\/*$/, '/') + this[ADDFSENTRY](base + entry) + }) + + if (zip) + source.on('data', chunk => { + zip.write(chunk) + }) + else + source.on('data', chunk => { + super[WRITE](chunk) + }) + } +} + +Pack.Sync = PackSync + +module.exports = Pack /***/ }), -/* 291 */ +/* 282 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const Buffer = __webpack_require__(280) -const MiniPass = __webpack_require__(283) -const Pax = __webpack_require__(292) -const Header = __webpack_require__(293) -const ReadEntry = __webpack_require__(289) -const fs = __webpack_require__(4) -const path = __webpack_require__(20) - -const types = __webpack_require__(290) -const maxReadSize = 16 * 1024 * 1024 -const PROCESS = Symbol('process') -const FILE = Symbol('file') -const DIRECTORY = Symbol('directory') -const SYMLINK = Symbol('symlink') -const HARDLINK = Symbol('hardlink') -const HEADER = Symbol('header') -const READ = Symbol('read') -const LSTAT = Symbol('lstat') -const ONLSTAT = Symbol('onlstat') -const ONREAD = Symbol('onread') -const ONREADLINK = Symbol('onreadlink') -const OPENFILE = Symbol('openfile') -const ONOPENFILE = Symbol('onopenfile') -const CLOSE = Symbol('close') -const MODE = Symbol('mode') -const warner = __webpack_require__(295) -const winchars = __webpack_require__(296) -const modeFix = __webpack_require__(297) +// Buffer in node 4.x < 4.5.0 doesn't have working Buffer.from +// or Buffer.alloc, and Buffer in node 10 deprecated the ctor. +// .M, this is fine .\^/M.. +let B = Buffer +/* istanbul ignore next */ +if (!B.alloc) { + B = __webpack_require__(283).Buffer +} +module.exports = B -const WriteEntry = warner(class WriteEntry extends MiniPass { - constructor (p, opt) { - opt = opt || {} - super(opt) - if (typeof p !== 'string') - throw new TypeError('path is required') - this.path = p - // suppress atime, ctime, uid, gid, uname, gname - this.portable = !!opt.portable - // until node has builtin pwnam functions, this'll have to do - this.myuid = process.getuid && process.getuid() - this.myuser = process.env.USER || '' - this.maxReadSize = opt.maxReadSize || maxReadSize - this.linkCache = opt.linkCache || new Map() - this.statCache = opt.statCache || new Map() - this.preservePaths = !!opt.preservePaths - this.cwd = opt.cwd || process.cwd() - this.strict = !!opt.strict - this.noPax = !!opt.noPax - this.noMtime = !!opt.noMtime - this.mtime = opt.mtime || null - if (typeof opt.onwarn === 'function') - this.on('warn', opt.onwarn) +/***/ }), +/* 283 */ +/***/ (function(module, exports, __webpack_require__) { - if (!this.preservePaths && path.win32.isAbsolute(p)) { - // absolutes on posix are also absolutes on win32 - // so we only need to test this one to get both - const parsed = path.win32.parse(p) - this.warn('stripping ' + parsed.root + ' from absolute path', p) - this.path = p.substr(parsed.root.length) - } +/* eslint-disable node/no-deprecated-api */ +var buffer = __webpack_require__(284) +var Buffer = buffer.Buffer - this.win32 = !!opt.win32 || process.platform === 'win32' - if (this.win32) { - this.path = winchars.decode(this.path.replace(/\\/g, '/')) - p = p.replace(/\\/g, '/') - } +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} - this.absolute = opt.absolute || path.resolve(this.cwd, p) +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} - if (this.path === '') - this.path = './' +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) - if (this.statCache.has(this.absolute)) - this[ONLSTAT](this.statCache.get(this.absolute)) - else - this[LSTAT]() +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') } + return Buffer(arg, encodingOrOffset, length) +} - [LSTAT] () { - fs.lstat(this.absolute, (er, stat) => { - if (er) - return this.emit('error', er) - this[ONLSTAT](stat) - }) +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') } - - [ONLSTAT] (stat) { - this.statCache.set(this.absolute, stat) - this.stat = stat - if (!stat.isFile()) - stat.size = 0 - this.type = getType(stat) - this.emit('stat', stat) - this[PROCESS]() + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) } + return buf +} - [PROCESS] () { - switch (this.type) { - case 'File': return this[FILE]() - case 'Directory': return this[DIRECTORY]() - case 'SymbolicLink': return this[SYMLINK]() - // unsupported types are ignored. - default: return this.end() - } +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') } + return Buffer(size) +} - [MODE] (mode) { - return modeFix(mode, this.type === 'Directory') +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') } + return buffer.SlowBuffer(size) +} - [HEADER] () { - if (this.type === 'Directory' && this.portable) - this.noMtime = true - this.header = new Header({ - path: this.path, - linkpath: this.linkpath, - // only the permissions and setuid/setgid/sticky bitflags - // not the higher-order bits that specify file type - mode: this[MODE](this.stat.mode), - uid: this.portable ? null : this.stat.uid, - gid: this.portable ? null : this.stat.gid, - size: this.stat.size, - mtime: this.noMtime ? null : this.mtime || this.stat.mtime, - type: this.type, - uname: this.portable ? null : - this.stat.uid === this.myuid ? this.myuser : '', - atime: this.portable ? null : this.stat.atime, - ctime: this.portable ? null : this.stat.ctime - }) +/***/ }), +/* 284 */ +/***/ (function(module, exports) { - if (this.header.encode() && !this.noPax) - this.write(new Pax({ - atime: this.portable ? null : this.header.atime, - ctime: this.portable ? null : this.header.ctime, - gid: this.portable ? null : this.header.gid, - mtime: this.noMtime ? null : this.mtime || this.header.mtime, - path: this.path, - linkpath: this.linkpath, - size: this.header.size, - uid: this.portable ? null : this.header.uid, - uname: this.portable ? null : this.header.uname, - dev: this.portable ? null : this.stat.dev, - ino: this.portable ? null : this.stat.ino, - nlink: this.portable ? null : this.stat.nlink - }).encode()) - this.write(this.header.block) - } +module.exports = require("buffer"); - [DIRECTORY] () { - if (this.path.substr(-1) !== '/') - this.path += '/' - this.stat.size = 0 - this[HEADER]() - this.end() - } +/***/ }), +/* 285 */ +/***/ (function(module, exports, __webpack_require__) { - [SYMLINK] () { - fs.readlink(this.absolute, (er, linkpath) => { - if (er) - return this.emit('error', er) - this[ONREADLINK](linkpath) - }) - } +"use strict"; - [ONREADLINK] (linkpath) { - this.linkpath = linkpath - this[HEADER]() - this.end() - } +const EE = __webpack_require__(137) +const Yallist = __webpack_require__(286) +const EOF = Symbol('EOF') +const MAYBE_EMIT_END = Symbol('maybeEmitEnd') +const EMITTED_END = Symbol('emittedEnd') +const CLOSED = Symbol('closed') +const READ = Symbol('read') +const FLUSH = Symbol('flush') +const doIter = process.env._MP_NO_ITERATOR_SYMBOLS_ !== '1' +const ASYNCITERATOR = doIter && Symbol.asyncIterator || Symbol('asyncIterator not implemented') +const ITERATOR = doIter && Symbol.iterator || Symbol('iterator not implemented') +const FLUSHCHUNK = Symbol('flushChunk') +const SD = __webpack_require__(288).StringDecoder +const ENCODING = Symbol('encoding') +const DECODER = Symbol('decoder') +const FLOWING = Symbol('flowing') +const RESUME = Symbol('resume') +const BUFFERLENGTH = Symbol('bufferLength') +const BUFFERPUSH = Symbol('bufferPush') +const BUFFERSHIFT = Symbol('bufferShift') +const OBJECTMODE = Symbol('objectMode') - [HARDLINK] (linkpath) { - this.type = 'Link' - this.linkpath = path.relative(this.cwd, linkpath) - this.stat.size = 0 - this[HEADER]() - this.end() +// Buffer in node 4.x < 4.5.0 doesn't have working Buffer.from +// or Buffer.alloc, and Buffer in node 10 deprecated the ctor. +// .M, this is fine .\^/M.. +let B = Buffer +/* istanbul ignore next */ +if (!B.alloc) { + B = __webpack_require__(283).Buffer +} + +module.exports = class MiniPass extends EE { + constructor (options) { + super() + this[FLOWING] = false + this.pipes = new Yallist() + this.buffer = new Yallist() + this[OBJECTMODE] = options && options.objectMode || false + if (this[OBJECTMODE]) + this[ENCODING] = null + else + this[ENCODING] = options && options.encoding || null + if (this[ENCODING] === 'buffer') + this[ENCODING] = null + this[DECODER] = this[ENCODING] ? new SD(this[ENCODING]) : null + this[EOF] = false + this[EMITTED_END] = false + this[CLOSED] = false + this.writable = true + this.readable = true + this[BUFFERLENGTH] = 0 } - [FILE] () { - if (this.stat.nlink > 1) { - const linkKey = this.stat.dev + ':' + this.stat.ino - if (this.linkCache.has(linkKey)) { - const linkpath = this.linkCache.get(linkKey) - if (linkpath.indexOf(this.cwd) === 0) - return this[HARDLINK](linkpath) - } - this.linkCache.set(linkKey, this.absolute) - } + get bufferLength () { return this[BUFFERLENGTH] } - this[HEADER]() - if (this.stat.size === 0) - return this.end() + get encoding () { return this[ENCODING] } + set encoding (enc) { + if (this[OBJECTMODE]) + throw new Error('cannot set encoding in objectMode') - this[OPENFILE]() - } + if (this[ENCODING] && enc !== this[ENCODING] && + (this[DECODER] && this[DECODER].lastNeed || this[BUFFERLENGTH])) + throw new Error('cannot change encoding') - [OPENFILE] () { - fs.open(this.absolute, 'r', (er, fd) => { - if (er) - return this.emit('error', er) - this[ONOPENFILE](fd) - }) - } + if (this[ENCODING] !== enc) { + this[DECODER] = enc ? new SD(enc) : null + if (this.buffer.length) + this.buffer = this.buffer.map(chunk => this[DECODER].write(chunk)) + } - [ONOPENFILE] (fd) { - const blockLen = 512 * Math.ceil(this.stat.size / 512) - const bufLen = Math.min(blockLen, this.maxReadSize) - const buf = Buffer.allocUnsafe(bufLen) - this[READ](fd, buf, 0, buf.length, 0, this.stat.size, blockLen) + this[ENCODING] = enc } - [READ] (fd, buf, offset, length, pos, remain, blockRemain) { - fs.read(fd, buf, offset, length, pos, (er, bytesRead) => { - if (er) - return this[CLOSE](fd, _ => this.emit('error', er)) - this[ONREAD](fd, buf, offset, length, pos, remain, blockRemain, bytesRead) - }) + setEncoding (enc) { + this.encoding = enc } - [CLOSE] (fd, cb) { - fs.close(fd, cb) - } + write (chunk, encoding, cb) { + if (this[EOF]) + throw new Error('write after end') - [ONREAD] (fd, buf, offset, length, pos, remain, blockRemain, bytesRead) { - if (bytesRead <= 0 && remain > 0) { - const er = new Error('encountered unexpected EOF') - er.path = this.absolute - er.syscall = 'read' - er.code = 'EOF' - this[CLOSE](fd) - return this.emit('error', er) - } + if (typeof encoding === 'function') + cb = encoding, encoding = 'utf8' - if (bytesRead > remain) { - const er = new Error('did not encounter expected EOF') - er.path = this.absolute - er.syscall = 'read' - er.code = 'EOF' - this[CLOSE](fd) - return this.emit('error', er) + if (!encoding) + encoding = 'utf8' + + // fast-path writing strings of same encoding to a stream with + // an empty buffer, skipping the buffer/decoder dance + if (typeof chunk === 'string' && !this[OBJECTMODE] && + // unless it is a string already ready for us to use + !(encoding === this[ENCODING] && !this[DECODER].lastNeed)) { + chunk = B.from(chunk, encoding) } - // null out the rest of the buffer, if we could fit the block padding - if (bytesRead === remain) { - for (let i = bytesRead; i < length && bytesRead < blockRemain; i++) { - buf[i + offset] = 0 - bytesRead ++ - remain ++ - } + if (B.isBuffer(chunk) && this[ENCODING]) + chunk = this[DECODER].write(chunk) + + try { + return this.flowing + ? (this.emit('data', chunk), this.flowing) + : (this[BUFFERPUSH](chunk), false) + } finally { + this.emit('readable') + if (cb) + cb() } + } - const writeBuf = offset === 0 && bytesRead === buf.length ? - buf : buf.slice(offset, offset + bytesRead) - remain -= bytesRead - blockRemain -= bytesRead - pos += bytesRead - offset += bytesRead + read (n) { + try { + if (this[BUFFERLENGTH] === 0 || n === 0 || n > this[BUFFERLENGTH]) + return null - this.write(writeBuf) + if (this[OBJECTMODE]) + n = null - if (!remain) { - if (blockRemain) - this.write(Buffer.alloc(blockRemain)) - this.end() - this[CLOSE](fd, _ => _) - return - } + if (this.buffer.length > 1 && !this[OBJECTMODE]) { + if (this.encoding) + this.buffer = new Yallist([ + Array.from(this.buffer).join('') + ]) + else + this.buffer = new Yallist([ + B.concat(Array.from(this.buffer), this[BUFFERLENGTH]) + ]) + } - if (offset >= length) { - buf = Buffer.allocUnsafe(length) - offset = 0 + return this[READ](n || null, this.buffer.head.value) + } finally { + this[MAYBE_EMIT_END]() } - length = buf.length - offset - this[READ](fd, buf, offset, length, pos, remain, blockRemain) } -}) -class WriteEntrySync extends WriteEntry { - constructor (path, opt) { - super(path, opt) - } + [READ] (n, chunk) { + if (n === chunk.length || n === null) + this[BUFFERSHIFT]() + else { + this.buffer.head.value = chunk.slice(n) + chunk = chunk.slice(0, n) + this[BUFFERLENGTH] -= n + } - [LSTAT] () { - this[ONLSTAT](fs.lstatSync(this.absolute)) + this.emit('data', chunk) + + if (!this.buffer.length && !this[EOF]) + this.emit('drain') + + return chunk } - [SYMLINK] () { - this[ONREADLINK](fs.readlinkSync(this.absolute)) + end (chunk, encoding, cb) { + if (typeof chunk === 'function') + cb = chunk, chunk = null + if (typeof encoding === 'function') + cb = encoding, encoding = 'utf8' + if (chunk) + this.write(chunk, encoding) + if (cb) + this.once('end', cb) + this[EOF] = true + this.writable = false + if (this.flowing) + this[MAYBE_EMIT_END]() } - [OPENFILE] () { - this[ONOPENFILE](fs.openSync(this.absolute, 'r')) + // don't let the internal resume be overwritten + [RESUME] () { + this[FLOWING] = true + this.emit('resume') + if (this.buffer.length) + this[FLUSH]() + else if (this[EOF]) + this[MAYBE_EMIT_END]() + else + this.emit('drain') } - [READ] (fd, buf, offset, length, pos, remain, blockRemain) { - let threw = true - try { - const bytesRead = fs.readSync(fd, buf, offset, length, pos) - this[ONREAD](fd, buf, offset, length, pos, remain, blockRemain, bytesRead) - threw = false - } finally { - if (threw) - try { this[CLOSE](fd) } catch (er) {} - } + resume () { + return this[RESUME]() } - [CLOSE] (fd) { - fs.closeSync(fd) + pause () { + this[FLOWING] = false } -} -const WriteEntryTar = warner(class WriteEntryTar extends MiniPass { - constructor (readEntry, opt) { - opt = opt || {} - super(opt) - this.preservePaths = !!opt.preservePaths - this.portable = !!opt.portable - this.strict = !!opt.strict - this.noPax = !!opt.noPax - this.noMtime = !!opt.noMtime + get flowing () { + return this[FLOWING] + } - this.readEntry = readEntry - this.type = readEntry.type - if (this.type === 'Directory' && this.portable) - this.noMtime = true + [BUFFERPUSH] (chunk) { + if (this[OBJECTMODE]) + this[BUFFERLENGTH] += 1 + else + this[BUFFERLENGTH] += chunk.length + return this.buffer.push(chunk) + } - this.path = readEntry.path - this.mode = this[MODE](readEntry.mode) - this.uid = this.portable ? null : readEntry.uid - this.gid = this.portable ? null : readEntry.gid - this.uname = this.portable ? null : readEntry.uname - this.gname = this.portable ? null : readEntry.gname - this.size = readEntry.size - this.mtime = this.noMtime ? null : opt.mtime || readEntry.mtime - this.atime = this.portable ? null : readEntry.atime - this.ctime = this.portable ? null : readEntry.ctime - this.linkpath = readEntry.linkpath + [BUFFERSHIFT] () { + if (this.buffer.length) { + if (this[OBJECTMODE]) + this[BUFFERLENGTH] -= 1 + else + this[BUFFERLENGTH] -= this.buffer.head.value.length + } + return this.buffer.shift() + } - if (typeof opt.onwarn === 'function') - this.on('warn', opt.onwarn) + [FLUSH] () { + do {} while (this[FLUSHCHUNK](this[BUFFERSHIFT]())) - if (path.isAbsolute(this.path) && !this.preservePaths) { - const parsed = path.parse(this.path) - this.warn( - 'stripping ' + parsed.root + ' from absolute path', - this.path - ) - this.path = this.path.substr(parsed.root.length) - } + if (!this.buffer.length && !this[EOF]) + this.emit('drain') + } - this.remain = readEntry.size - this.blockRemain = readEntry.startBlockSize + [FLUSHCHUNK] (chunk) { + return chunk ? (this.emit('data', chunk), this.flowing) : false + } - this.header = new Header({ - path: this.path, - linkpath: this.linkpath, - // only the permissions and setuid/setgid/sticky bitflags - // not the higher-order bits that specify file type - mode: this.mode, - uid: this.portable ? null : this.uid, - gid: this.portable ? null : this.gid, - size: this.size, - mtime: this.noMtime ? null : this.mtime, - type: this.type, - uname: this.portable ? null : this.uname, - atime: this.portable ? null : this.atime, - ctime: this.portable ? null : this.ctime - }) + pipe (dest, opts) { + if (dest === process.stdout || dest === process.stderr) + (opts = opts || {}).end = false + const p = { dest: dest, opts: opts, ondrain: _ => this[RESUME]() } + this.pipes.push(p) - if (this.header.encode() && !this.noPax) - super.write(new Pax({ - atime: this.portable ? null : this.atime, - ctime: this.portable ? null : this.ctime, - gid: this.portable ? null : this.gid, - mtime: this.noMtime ? null : this.mtime, - path: this.path, - linkpath: this.linkpath, - size: this.size, - uid: this.portable ? null : this.uid, - uname: this.portable ? null : this.uname, - dev: this.portable ? null : this.readEntry.dev, - ino: this.portable ? null : this.readEntry.ino, - nlink: this.portable ? null : this.readEntry.nlink - }).encode()) + dest.on('drain', p.ondrain) + this[RESUME]() + return dest + } - super.write(this.header.block) - readEntry.pipe(this) + addListener (ev, fn) { + return this.on(ev, fn) } - [MODE] (mode) { - return modeFix(mode, this.type === 'Directory') + on (ev, fn) { + try { + return super.on(ev, fn) + } finally { + if (ev === 'data' && !this.pipes.length && !this.flowing) + this[RESUME]() + else if (ev === 'end' && this[EMITTED_END]) { + super.emit('end') + this.removeAllListeners('end') + } + } } - write (data) { - const writeLen = data.length - if (writeLen > this.blockRemain) - throw new Error('writing more to entry than is appropriate') - this.blockRemain -= writeLen - return super.write(data) + get emittedEnd () { + return this[EMITTED_END] } - end () { - if (this.blockRemain) - this.write(Buffer.alloc(this.blockRemain)) - return super.end() + [MAYBE_EMIT_END] () { + if (!this[EMITTED_END] && this.buffer.length === 0 && this[EOF]) { + this.emit('end') + this.emit('prefinish') + this.emit('finish') + if (this[CLOSED]) + this.emit('close') + } } -}) -WriteEntry.Sync = WriteEntrySync -WriteEntry.Tar = WriteEntryTar + emit (ev, data) { + if (ev === 'data') { + if (!data) + return -const getType = stat => - stat.isFile() ? 'File' - : stat.isDirectory() ? 'Directory' - : stat.isSymbolicLink() ? 'SymbolicLink' - : 'Unsupported' + if (this.pipes.length) + this.pipes.forEach(p => p.dest.write(data) || this.pause()) + } else if (ev === 'end') { + if (this[EMITTED_END] === true) + return -module.exports = WriteEntry + this[EMITTED_END] = true + this.readable = false + if (this[DECODER]) { + data = this[DECODER].end() + if (data) { + this.pipes.forEach(p => p.dest.write(data)) + super.emit('data', data) + } + } -/***/ }), -/* 292 */ -/***/ (function(module, exports, __webpack_require__) { + this.pipes.forEach(p => { + p.dest.removeListener('drain', p.ondrain) + if (!p.opts || p.opts.end !== false) + p.dest.end() + }) + } else if (ev === 'close') { + this[CLOSED] = true + // don't emit close before 'end' and 'finish' + if (!this[EMITTED_END]) + return + } -"use strict"; + const args = new Array(arguments.length) + args[0] = ev + args[1] = data + if (arguments.length > 2) { + for (let i = 2; i < arguments.length; i++) { + args[i] = arguments[i] + } + } -const Buffer = __webpack_require__(280) -const Header = __webpack_require__(293) -const path = __webpack_require__(20) + try { + return super.emit.apply(this, args) + } finally { + if (ev !== 'end') + this[MAYBE_EMIT_END]() + else + this.removeAllListeners('end') + } + } -class Pax { - constructor (obj, global) { - this.atime = obj.atime || null - this.charset = obj.charset || null - this.comment = obj.comment || null - this.ctime = obj.ctime || null - this.gid = obj.gid || null - this.gname = obj.gname || null - this.linkpath = obj.linkpath || null - this.mtime = obj.mtime || null - this.path = obj.path || null - this.size = obj.size || null - this.uid = obj.uid || null - this.uname = obj.uname || null - this.dev = obj.dev || null - this.ino = obj.ino || null - this.nlink = obj.nlink || null - this.global = global || false + // const all = await stream.collect() + collect () { + return new Promise((resolve, reject) => { + const buf = [] + this.on('data', c => buf.push(c)) + this.on('end', () => resolve(buf)) + this.on('error', reject) + }) } - encode () { - const body = this.encodeBody() - if (body === '') - return null - - const bodyLen = Buffer.byteLength(body) - // round up to 512 bytes - // add 512 for header - const bufLen = 512 * Math.ceil(1 + bodyLen / 512) - const buf = Buffer.allocUnsafe(bufLen) - - // 0-fill the header section, it might not hit every field - for (let i = 0; i < 512; i++) { - buf[i] = 0 - } - - new Header({ - // XXX split the path - // then the path should be PaxHeader + basename, but less than 99, - // prepend with the dirname - path: ('PaxHeader/' + path.basename(this.path)).slice(0, 99), - mode: this.mode || 0o644, - uid: this.uid || null, - gid: this.gid || null, - size: bodyLen, - mtime: this.mtime || null, - type: this.global ? 'GlobalExtendedHeader' : 'ExtendedHeader', - linkpath: '', - uname: this.uname || '', - gname: this.gname || '', - devmaj: 0, - devmin: 0, - atime: this.atime || null, - ctime: this.ctime || null - }).encode(buf) + // for await (let chunk of stream) + [ASYNCITERATOR] () { + const next = () => { + const res = this.read() + if (res !== null) + return Promise.resolve({ done: false, value: res }) - buf.write(body, 512, bodyLen, 'utf8') + if (this[EOF]) + return Promise.resolve({ done: true }) - // null pad after the body - for (let i = bodyLen + 512; i < buf.length; i++) { - buf[i] = 0 + let resolve = null + let reject = null + const onerr = er => { + this.removeListener('data', ondata) + this.removeListener('end', onend) + reject(er) + } + const ondata = value => { + this.removeListener('error', onerr) + this.removeListener('end', onend) + this.pause() + resolve({ value: value, done: !!this[EOF] }) + } + const onend = () => { + this.removeListener('error', onerr) + this.removeListener('data', ondata) + resolve({ done: true }) + } + return new Promise((res, rej) => { + reject = rej + resolve = res + this.once('error', onerr) + this.once('end', onend) + this.once('data', ondata) + }) } - return buf - } - - encodeBody () { - return ( - this.encodeField('path') + - this.encodeField('ctime') + - this.encodeField('atime') + - this.encodeField('dev') + - this.encodeField('ino') + - this.encodeField('nlink') + - this.encodeField('charset') + - this.encodeField('comment') + - this.encodeField('gid') + - this.encodeField('gname') + - this.encodeField('linkpath') + - this.encodeField('mtime') + - this.encodeField('size') + - this.encodeField('uid') + - this.encodeField('uname') - ) + return { next } } - encodeField (field) { - if (this[field] === null || this[field] === undefined) - return '' - const v = this[field] instanceof Date ? this[field].getTime() / 1000 - : this[field] - const s = ' ' + - (field === 'dev' || field === 'ino' || field === 'nlink' - ? 'SCHILY.' : '') + - field + '=' + v + '\n' - const byteLen = Buffer.byteLength(s) - // the digits includes the length of the digits in ascii base-10 - // so if it's 9 characters, then adding 1 for the 9 makes it 10 - // which makes it 11 chars. - let digits = Math.floor(Math.log(byteLen) / Math.log(10)) + 1 - if (byteLen + digits >= Math.pow(10, digits)) - digits += 1 - const len = digits + byteLen - return len + s + // for (let chunk of stream) + [ITERATOR] () { + const next = () => { + const value = this.read() + const done = value === null + return { value, done } + } + return { next } } } -Pax.parse = (string, ex, g) => new Pax(merge(parseKV(string), ex), g) - -const merge = (a, b) => - b ? Object.keys(a).reduce((s, k) => (s[k] = a[k], s), b) : a - -const parseKV = string => - string - .replace(/\n$/, '') - .split('\n') - .reduce(parseKVLine, Object.create(null)) - -const parseKVLine = (set, line) => { - const n = parseInt(line, 10) - - // XXX Values with \n in them will fail this. - // Refactor to not be a naive line-by-line parse. - if (n !== Buffer.byteLength(line) + 1) - return set - - line = line.substr((n + ' ').length) - const kv = line.split('=') - const k = kv.shift().replace(/^SCHILY\.(dev|ino|nlink)/, '$1') - if (!k) - return set - - const v = kv.join('=') - set[k] = /^([A-Z]+\.)?([mac]|birth|creation)time$/.test(k) - ? new Date(v * 1000) - : /^[0-9]+$/.test(v) ? +v - : v - return set -} - -module.exports = Pax - /***/ }), -/* 293 */ +/* 286 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -// parse a 512-byte header block to a data object, or vice-versa -// encode returns `true` if a pax extended header is needed, because -// the data could not be faithfully encoded in a simple header. -// (Also, check header.needPax to see if it needs a pax header.) - -const Buffer = __webpack_require__(280) -const types = __webpack_require__(290) -const pathModule = __webpack_require__(20).posix -const large = __webpack_require__(294) - -const SLURP = Symbol('slurp') -const TYPE = Symbol('type') - -class Header { - constructor (data, off, ex, gex) { - this.cksumValid = false - this.needPax = false - this.nullBlock = false +module.exports = Yallist - this.block = null - this.path = null - this.mode = null - this.uid = null - this.gid = null - this.size = null - this.mtime = null - this.cksum = null - this[TYPE] = '0' - this.linkpath = null - this.uname = null - this.gname = null - this.devmaj = 0 - this.devmin = 0 - this.atime = null - this.ctime = null +Yallist.Node = Node +Yallist.create = Yallist - if (Buffer.isBuffer(data)) - this.decode(data, off || 0, ex, gex) - else if (data) - this.set(data) +function Yallist (list) { + var self = this + if (!(self instanceof Yallist)) { + self = new Yallist() } - decode (buf, off, ex, gex) { - if (!off) - off = 0 - - if (!buf || !(buf.length >= off + 512)) - throw new Error('need 512 bytes for header') + self.tail = null + self.head = null + self.length = 0 - this.path = decString(buf, off, 100) - this.mode = decNumber(buf, off + 100, 8) - this.uid = decNumber(buf, off + 108, 8) - this.gid = decNumber(buf, off + 116, 8) - this.size = decNumber(buf, off + 124, 12) - this.mtime = decDate(buf, off + 136, 12) - this.cksum = decNumber(buf, off + 148, 12) + if (list && typeof list.forEach === 'function') { + list.forEach(function (item) { + self.push(item) + }) + } else if (arguments.length > 0) { + for (var i = 0, l = arguments.length; i < l; i++) { + self.push(arguments[i]) + } + } - // if we have extended or global extended headers, apply them now - // See https://github.com/npm/node-tar/pull/187 - this[SLURP](ex) - this[SLURP](gex, true) + return self +} - // old tar versions marked dirs as a file with a trailing / - this[TYPE] = decString(buf, off + 156, 1) - if (this[TYPE] === '') - this[TYPE] = '0' - if (this[TYPE] === '0' && this.path.substr(-1) === '/') - this[TYPE] = '5' +Yallist.prototype.removeNode = function (node) { + if (node.list !== this) { + throw new Error('removing node which does not belong to this list') + } - // tar implementations sometimes incorrectly put the stat(dir).size - // as the size in the tarball, even though Directory entries are - // not able to have any body at all. In the very rare chance that - // it actually DOES have a body, we weren't going to do anything with - // it anyway, and it'll just be a warning about an invalid header. - if (this[TYPE] === '5') - this.size = 0 + var next = node.next + var prev = node.prev - this.linkpath = decString(buf, off + 157, 100) - if (buf.slice(off + 257, off + 265).toString() === 'ustar\u000000') { - this.uname = decString(buf, off + 265, 32) - this.gname = decString(buf, off + 297, 32) - this.devmaj = decNumber(buf, off + 329, 8) - this.devmin = decNumber(buf, off + 337, 8) - if (buf[off + 475] !== 0) { - // definitely a prefix, definitely >130 chars. - const prefix = decString(buf, off + 345, 155) - this.path = prefix + '/' + this.path - } else { - const prefix = decString(buf, off + 345, 130) - if (prefix) - this.path = prefix + '/' + this.path - this.atime = decDate(buf, off + 476, 12) - this.ctime = decDate(buf, off + 488, 12) - } - } + if (next) { + next.prev = prev + } - let sum = 8 * 0x20 - for (let i = off; i < off + 148; i++) { - sum += buf[i] - } - for (let i = off + 156; i < off + 512; i++) { - sum += buf[i] - } - this.cksumValid = sum === this.cksum - if (this.cksum === null && sum === 8 * 0x20) - this.nullBlock = true + if (prev) { + prev.next = next } - [SLURP] (ex, global) { - for (let k in ex) { - // we slurp in everything except for the path attribute in - // a global extended header, because that's weird. - if (ex[k] !== null && ex[k] !== undefined && - !(global && k === 'path')) - this[k] = ex[k] - } + if (node === this.head) { + this.head = next + } + if (node === this.tail) { + this.tail = prev } - encode (buf, off) { - if (!buf) { - buf = this.block = Buffer.alloc(512) - off = 0 - } + node.list.length-- + node.next = null + node.prev = null + node.list = null +} - if (!off) - off = 0 +Yallist.prototype.unshiftNode = function (node) { + if (node === this.head) { + return + } - if (!(buf.length >= off + 512)) - throw new Error('need 512 bytes for header') + if (node.list) { + node.list.removeNode(node) + } - const prefixSize = this.ctime || this.atime ? 130 : 155 - const split = splitPrefix(this.path || '', prefixSize) - const path = split[0] - const prefix = split[1] - this.needPax = split[2] + var head = this.head + node.list = this + node.next = head + if (head) { + head.prev = node + } - this.needPax = encString(buf, off, 100, path) || this.needPax - this.needPax = encNumber(buf, off + 100, 8, this.mode) || this.needPax - this.needPax = encNumber(buf, off + 108, 8, this.uid) || this.needPax - this.needPax = encNumber(buf, off + 116, 8, this.gid) || this.needPax - this.needPax = encNumber(buf, off + 124, 12, this.size) || this.needPax - this.needPax = encDate(buf, off + 136, 12, this.mtime) || this.needPax - buf[off + 156] = this[TYPE].charCodeAt(0) - this.needPax = encString(buf, off + 157, 100, this.linkpath) || this.needPax - buf.write('ustar\u000000', off + 257, 8) - this.needPax = encString(buf, off + 265, 32, this.uname) || this.needPax - this.needPax = encString(buf, off + 297, 32, this.gname) || this.needPax - this.needPax = encNumber(buf, off + 329, 8, this.devmaj) || this.needPax - this.needPax = encNumber(buf, off + 337, 8, this.devmin) || this.needPax - this.needPax = encString(buf, off + 345, prefixSize, prefix) || this.needPax - if (buf[off + 475] !== 0) - this.needPax = encString(buf, off + 345, 155, prefix) || this.needPax - else { - this.needPax = encString(buf, off + 345, 130, prefix) || this.needPax - this.needPax = encDate(buf, off + 476, 12, this.atime) || this.needPax - this.needPax = encDate(buf, off + 488, 12, this.ctime) || this.needPax - } + this.head = node + if (!this.tail) { + this.tail = node + } + this.length++ +} - let sum = 8 * 0x20 - for (let i = off; i < off + 148; i++) { - sum += buf[i] - } - for (let i = off + 156; i < off + 512; i++) { - sum += buf[i] - } - this.cksum = sum - encNumber(buf, off + 148, 8, this.cksum) - this.cksumValid = true +Yallist.prototype.pushNode = function (node) { + if (node === this.tail) { + return + } - return this.needPax + if (node.list) { + node.list.removeNode(node) } - set (data) { - for (let i in data) { - if (data[i] !== null && data[i] !== undefined) - this[i] = data[i] - } + var tail = this.tail + node.list = this + node.prev = tail + if (tail) { + tail.next = node } - get type () { - return types.name.get(this[TYPE]) || this[TYPE] + this.tail = node + if (!this.head) { + this.head = node } + this.length++ +} - get typeKey () { - return this[TYPE] +Yallist.prototype.push = function () { + for (var i = 0, l = arguments.length; i < l; i++) { + push(this, arguments[i]) } + return this.length +} - set type (type) { - if (types.code.has(type)) - this[TYPE] = types.code.get(type) - else - this[TYPE] = type +Yallist.prototype.unshift = function () { + for (var i = 0, l = arguments.length; i < l; i++) { + unshift(this, arguments[i]) } + return this.length } -const splitPrefix = (p, prefixSize) => { - const pathSize = 100 - let pp = p - let prefix = '' - let ret - const root = pathModule.parse(p).root || '.' +Yallist.prototype.pop = function () { + if (!this.tail) { + return undefined + } - if (Buffer.byteLength(pp) < pathSize) - ret = [pp, prefix, false] - else { - // first set prefix to the dir, and path to the base - prefix = pathModule.dirname(pp) - pp = pathModule.basename(pp) + var res = this.tail.value + this.tail = this.tail.prev + if (this.tail) { + this.tail.next = null + } else { + this.head = null + } + this.length-- + return res +} - do { - // both fit! - if (Buffer.byteLength(pp) <= pathSize && - Buffer.byteLength(prefix) <= prefixSize) - ret = [pp, prefix, false] +Yallist.prototype.shift = function () { + if (!this.head) { + return undefined + } - // prefix fits in prefix, but path doesn't fit in path - else if (Buffer.byteLength(pp) > pathSize && - Buffer.byteLength(prefix) <= prefixSize) - ret = [pp.substr(0, pathSize - 1), prefix, true] + var res = this.head.value + this.head = this.head.next + if (this.head) { + this.head.prev = null + } else { + this.tail = null + } + this.length-- + return res +} - else { - // make path take a bit from prefix - pp = pathModule.join(pathModule.basename(prefix), pp) - prefix = pathModule.dirname(prefix) - } - } while (prefix !== root && !ret) +Yallist.prototype.forEach = function (fn, thisp) { + thisp = thisp || this + for (var walker = this.head, i = 0; walker !== null; i++) { + fn.call(thisp, walker.value, i, this) + walker = walker.next + } +} - // at this point, found no resolution, just truncate - if (!ret) - ret = [p.substr(0, pathSize - 1), '', true] +Yallist.prototype.forEachReverse = function (fn, thisp) { + thisp = thisp || this + for (var walker = this.tail, i = this.length - 1; walker !== null; i--) { + fn.call(thisp, walker.value, i, this) + walker = walker.prev } - return ret } -const decString = (buf, off, size) => - buf.slice(off, off + size).toString('utf8').replace(/\0.*/, '') +Yallist.prototype.get = function (n) { + for (var i = 0, walker = this.head; walker !== null && i < n; i++) { + // abort out of the list early if we hit a cycle + walker = walker.next + } + if (i === n && walker !== null) { + return walker.value + } +} -const decDate = (buf, off, size) => - numToDate(decNumber(buf, off, size)) - -const numToDate = num => num === null ? null : new Date(num * 1000) - -const decNumber = (buf, off, size) => - buf[off] & 0x80 ? large.parse(buf.slice(off, off + size)) - : decSmallNumber(buf, off, size) - -const nanNull = value => isNaN(value) ? null : value - -const decSmallNumber = (buf, off, size) => - nanNull(parseInt( - buf.slice(off, off + size) - .toString('utf8').replace(/\0.*$/, '').trim(), 8)) - -// the maximum encodable as a null-terminated octal, by field size -const MAXNUM = { - 12: 0o77777777777, - 8 : 0o7777777 +Yallist.prototype.getReverse = function (n) { + for (var i = 0, walker = this.tail; walker !== null && i < n; i++) { + // abort out of the list early if we hit a cycle + walker = walker.prev + } + if (i === n && walker !== null) { + return walker.value + } } -const encNumber = (buf, off, size, number) => - number === null ? false : - number > MAXNUM[size] || number < 0 - ? (large.encode(number, buf.slice(off, off + size)), true) - : (encSmallNumber(buf, off, size, number), false) - -const encSmallNumber = (buf, off, size, number) => - buf.write(octalString(number, size), off, size, 'ascii') +Yallist.prototype.map = function (fn, thisp) { + thisp = thisp || this + var res = new Yallist() + for (var walker = this.head; walker !== null;) { + res.push(fn.call(thisp, walker.value, this)) + walker = walker.next + } + return res +} -const octalString = (number, size) => - padOctal(Math.floor(number).toString(8), size) +Yallist.prototype.mapReverse = function (fn, thisp) { + thisp = thisp || this + var res = new Yallist() + for (var walker = this.tail; walker !== null;) { + res.push(fn.call(thisp, walker.value, this)) + walker = walker.prev + } + return res +} -const padOctal = (string, size) => - (string.length === size - 1 ? string - : new Array(size - string.length - 1).join('0') + string + ' ') + '\0' +Yallist.prototype.reduce = function (fn, initial) { + var acc + var walker = this.head + if (arguments.length > 1) { + acc = initial + } else if (this.head) { + walker = this.head.next + acc = this.head.value + } else { + throw new TypeError('Reduce of empty list with no initial value') + } -const encDate = (buf, off, size, date) => - date === null ? false : - encNumber(buf, off, size, date.getTime() / 1000) + for (var i = 0; walker !== null; i++) { + acc = fn(acc, walker.value, i) + walker = walker.next + } -// enough to fill the longest string we've got -const NULLS = new Array(156).join('\0') -// pad with nulls, return true if it's longer or non-ascii -const encString = (buf, off, size, string) => - string === null ? false : - (buf.write(string + NULLS, off, size, 'utf8'), - string.length !== Buffer.byteLength(string) || string.length > size) + return acc +} -module.exports = Header +Yallist.prototype.reduceReverse = function (fn, initial) { + var acc + var walker = this.tail + if (arguments.length > 1) { + acc = initial + } else if (this.tail) { + walker = this.tail.prev + acc = this.tail.value + } else { + throw new TypeError('Reduce of empty list with no initial value') + } + for (var i = this.length - 1; walker !== null; i--) { + acc = fn(acc, walker.value, i) + walker = walker.prev + } -/***/ }), -/* 294 */ -/***/ (function(module, exports, __webpack_require__) { + return acc +} -"use strict"; +Yallist.prototype.toArray = function () { + var arr = new Array(this.length) + for (var i = 0, walker = this.head; walker !== null; i++) { + arr[i] = walker.value + walker = walker.next + } + return arr +} -// Tar can encode large and negative numbers using a leading byte of -// 0xff for negative, and 0x80 for positive. +Yallist.prototype.toArrayReverse = function () { + var arr = new Array(this.length) + for (var i = 0, walker = this.tail; walker !== null; i++) { + arr[i] = walker.value + walker = walker.prev + } + return arr +} -const encode = exports.encode = (num, buf) => { - if (!Number.isSafeInteger(num)) - // The number is so large that javascript cannot represent it with integer - // precision. - throw TypeError('cannot encode number outside of javascript safe integer range') - else if (num < 0) - encodeNegative(num, buf) - else - encodePositive(num, buf) - return buf +Yallist.prototype.slice = function (from, to) { + to = to || this.length + if (to < 0) { + to += this.length + } + from = from || 0 + if (from < 0) { + from += this.length + } + var ret = new Yallist() + if (to < from || to < 0) { + return ret + } + if (from < 0) { + from = 0 + } + if (to > this.length) { + to = this.length + } + for (var i = 0, walker = this.head; walker !== null && i < from; i++) { + walker = walker.next + } + for (; walker !== null && i < to; i++, walker = walker.next) { + ret.push(walker.value) + } + return ret } -const encodePositive = (num, buf) => { - buf[0] = 0x80 +Yallist.prototype.sliceReverse = function (from, to) { + to = to || this.length + if (to < 0) { + to += this.length + } + from = from || 0 + if (from < 0) { + from += this.length + } + var ret = new Yallist() + if (to < from || to < 0) { + return ret + } + if (from < 0) { + from = 0 + } + if (to > this.length) { + to = this.length + } + for (var i = this.length, walker = this.tail; walker !== null && i > to; i--) { + walker = walker.prev + } + for (; walker !== null && i > from; i--, walker = walker.prev) { + ret.push(walker.value) + } + return ret +} - for (var i = buf.length; i > 1; i--) { - buf[i-1] = num & 0xff - num = Math.floor(num / 0x100) +Yallist.prototype.reverse = function () { + var head = this.head + var tail = this.tail + for (var walker = head; walker !== null; walker = walker.prev) { + var p = walker.prev + walker.prev = walker.next + walker.next = p } + this.head = tail + this.tail = head + return this } -const encodeNegative = (num, buf) => { - buf[0] = 0xff - var flipped = false - num = num * -1 - for (var i = buf.length; i > 1; i--) { - var byte = num & 0xff - num = Math.floor(num / 0x100) - if (flipped) - buf[i-1] = onesComp(byte) - else if (byte === 0) - buf[i-1] = 0 - else { - flipped = true - buf[i-1] = twosComp(byte) - } +function push (self, item) { + self.tail = new Node(item, self.tail, null, self) + if (!self.head) { + self.head = self.tail } + self.length++ } -const parse = exports.parse = (buf) => { - var post = buf[buf.length - 1] - var pre = buf[0] - var value; - if (pre === 0x80) - value = pos(buf.slice(1, buf.length)) - else if (pre === 0xff) - value = twos(buf) - else - throw TypeError('invalid base256 encoding') +function unshift (self, item) { + self.head = new Node(item, null, self.head, self) + if (!self.tail) { + self.tail = self.head + } + self.length++ +} - if (!Number.isSafeInteger(value)) - // The number is so large that javascript cannot represent it with integer - // precision. - throw TypeError('parsed number outside of javascript safe integer range') +function Node (value, prev, next, list) { + if (!(this instanceof Node)) { + return new Node(value, prev, next, list) + } - return value -} + this.list = list + this.value = value -const twos = (buf) => { - var len = buf.length - var sum = 0 - var flipped = false - for (var i = len - 1; i > -1; i--) { - var byte = buf[i] - var f - if (flipped) - f = onesComp(byte) - else if (byte === 0) - f = byte - else { - flipped = true - f = twosComp(byte) - } - if (f !== 0) - sum -= f * Math.pow(256, len - i - 1) + if (prev) { + prev.next = this + this.prev = prev + } else { + this.prev = null } - return sum -} -const pos = (buf) => { - var len = buf.length - var sum = 0 - for (var i = len - 1; i > -1; i--) { - var byte = buf[i] - if (byte !== 0) - sum += byte * Math.pow(256, len - i - 1) + if (next) { + next.prev = this + this.next = next + } else { + this.next = null } - return sum } -const onesComp = byte => (0xff ^ byte) & 0xff - -const twosComp = byte => ((0xff ^ byte) + 1) & 0xff +try { + // add if support for Symbol.iterator is present + __webpack_require__(287)(Yallist) +} catch (er) {} /***/ }), -/* 295 */ +/* 287 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = Base => class extends Base { - warn (msg, data) { - if (!this.strict) - this.emit('warn', msg, data) - else if (data instanceof Error) - this.emit('error', data) - else { - const er = new Error(msg) - er.data = data - this.emit('error', er) +module.exports = function (Yallist) { + Yallist.prototype[Symbol.iterator] = function* () { + for (let walker = this.head; walker; walker = walker.next) { + yield walker.value } } } /***/ }), -/* 296 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - +/* 288 */ +/***/ (function(module, exports) { -// When writing files on Windows, translate the characters to their -// 0xf000 higher-encoded versions. +module.exports = require("string_decoder"); -const raw = [ - '|', - '<', - '>', - '?', - ':' -] +/***/ }), +/* 289 */ +/***/ (function(module, exports, __webpack_require__) { -const win = raw.map(char => - String.fromCharCode(0xf000 + char.charCodeAt(0))) +"use strict"; -const toWin = new Map(raw.map((char, i) => [char, win[i]])) -const toRaw = new Map(win.map((char, i) => [char, raw[i]])) -module.exports = { - encode: s => raw.reduce((s, c) => s.split(c).join(toWin.get(c)), s), - decode: s => win.reduce((s, c) => s.split(c).join(toRaw.get(c)), s) -} +const assert = __webpack_require__(46) +const Buffer = __webpack_require__(284).Buffer +const realZlib = __webpack_require__(82) +const constants = exports.constants = __webpack_require__(290) +const MiniPass = __webpack_require__(285) -/***/ }), -/* 297 */ -/***/ (function(module, exports, __webpack_require__) { +const OriginalBufferConcat = Buffer.concat -"use strict"; +class ZlibError extends Error { + constructor (msg, errno) { + super('zlib: ' + msg) + this.errno = errno + this.code = codes.get(errno) + } -module.exports = (mode, isDir) => { - mode &= 0o7777 - // if dirs are readable, then they should be listable - if (isDir) { - if (mode & 0o400) - mode |= 0o100 - if (mode & 0o40) - mode |= 0o10 - if (mode & 0o4) - mode |= 0o1 + get name () { + return 'ZlibError' } - return mode } +// translation table for return codes. +const codes = new Map([ + [constants.Z_OK, 'Z_OK'], + [constants.Z_STREAM_END, 'Z_STREAM_END'], + [constants.Z_NEED_DICT, 'Z_NEED_DICT'], + [constants.Z_ERRNO, 'Z_ERRNO'], + [constants.Z_STREAM_ERROR, 'Z_STREAM_ERROR'], + [constants.Z_DATA_ERROR, 'Z_DATA_ERROR'], + [constants.Z_MEM_ERROR, 'Z_MEM_ERROR'], + [constants.Z_BUF_ERROR, 'Z_BUF_ERROR'], + [constants.Z_VERSION_ERROR, 'Z_VERSION_ERROR'] +]) -/***/ }), -/* 298 */ -/***/ (function(module, exports, __webpack_require__) { +const validFlushFlags = new Set([ + constants.Z_NO_FLUSH, + constants.Z_PARTIAL_FLUSH, + constants.Z_SYNC_FLUSH, + constants.Z_FULL_FLUSH, + constants.Z_FINISH, + constants.Z_BLOCK +]) -"use strict"; +const strategies = new Set([ + constants.Z_FILTERED, + constants.Z_HUFFMAN_ONLY, + constants.Z_RLE, + constants.Z_FIXED, + constants.Z_DEFAULT_STRATEGY +]) -const MiniPass = __webpack_require__(283) -const EE = __webpack_require__(137).EventEmitter -const fs = __webpack_require__(4) +// the Zlib class they all inherit from +// This thing manages the queue of requests, and returns +// true or false if there is anything in the queue when +// you call the .write() method. +const _opts = Symbol('opts') +const _flushFlag = Symbol('flushFlag') +const _finishFlush = Symbol('finishFlush') +const _handle = Symbol('handle') +const _onError = Symbol('onError') +const _level = Symbol('level') +const _strategy = Symbol('strategy') +const _ended = Symbol('ended') -// for writev -const binding = process.binding('fs') -const writeBuffers = binding.writeBuffers -const FSReqWrap = binding.FSReqWrap || binding.FSReqCallback +class Zlib extends MiniPass { + constructor (opts, mode) { + super(opts) + this[_ended] = false + this[_opts] = opts = opts || {} + if (opts.flush && !validFlushFlags.has(opts.flush)) { + throw new TypeError('Invalid flush flag: ' + opts.flush) + } + if (opts.finishFlush && !validFlushFlags.has(opts.finishFlush)) { + throw new TypeError('Invalid flush flag: ' + opts.finishFlush) + } -const _autoClose = Symbol('_autoClose') -const _close = Symbol('_close') -const _ended = Symbol('_ended') -const _fd = Symbol('_fd') -const _finished = Symbol('_finished') -const _flags = Symbol('_flags') -const _flush = Symbol('_flush') -const _handleChunk = Symbol('_handleChunk') -const _makeBuf = Symbol('_makeBuf') -const _mode = Symbol('_mode') -const _needDrain = Symbol('_needDrain') -const _onerror = Symbol('_onerror') -const _onopen = Symbol('_onopen') -const _onread = Symbol('_onread') -const _onwrite = Symbol('_onwrite') -const _open = Symbol('_open') -const _path = Symbol('_path') -const _pos = Symbol('_pos') -const _queue = Symbol('_queue') -const _read = Symbol('_read') -const _readSize = Symbol('_readSize') -const _reading = Symbol('_reading') -const _remain = Symbol('_remain') -const _size = Symbol('_size') -const _write = Symbol('_write') -const _writing = Symbol('_writing') -const _defaultFlag = Symbol('_defaultFlag') + this[_flushFlag] = opts.flush || constants.Z_NO_FLUSH + this[_finishFlush] = typeof opts.finishFlush !== 'undefined' ? + opts.finishFlush : constants.Z_FINISH -class ReadStream extends MiniPass { - constructor (path, opt) { - opt = opt || {} - super(opt) + if (opts.chunkSize) { + if (opts.chunkSize < constants.Z_MIN_CHUNK) { + throw new RangeError('Invalid chunk size: ' + opts.chunkSize) + } + } - this.writable = false + if (opts.windowBits) { + if (opts.windowBits < constants.Z_MIN_WINDOWBITS || + opts.windowBits > constants.Z_MAX_WINDOWBITS) { + throw new RangeError('Invalid windowBits: ' + opts.windowBits) + } + } - if (typeof path !== 'string') - throw new TypeError('path must be a string') + if (opts.level) { + if (opts.level < constants.Z_MIN_LEVEL || + opts.level > constants.Z_MAX_LEVEL) { + throw new RangeError('Invalid compression level: ' + opts.level) + } + } - this[_fd] = typeof opt.fd === 'number' ? opt.fd : null - this[_path] = path - this[_readSize] = opt.readSize || 16*1024*1024 - this[_reading] = false - this[_size] = typeof opt.size === 'number' ? opt.size : Infinity - this[_remain] = this[_size] - this[_autoClose] = typeof opt.autoClose === 'boolean' ? - opt.autoClose : true + if (opts.memLevel) { + if (opts.memLevel < constants.Z_MIN_MEMLEVEL || + opts.memLevel > constants.Z_MAX_MEMLEVEL) { + throw new RangeError('Invalid memLevel: ' + opts.memLevel) + } + } - if (typeof this[_fd] === 'number') - this[_read]() - else - this[_open]() - } + if (opts.strategy && !(strategies.has(opts.strategy))) + throw new TypeError('Invalid strategy: ' + opts.strategy) - get fd () { return this[_fd] } - get path () { return this[_path] } + if (opts.dictionary) { + if (!(opts.dictionary instanceof Buffer)) { + throw new TypeError('Invalid dictionary: it should be a Buffer instance') + } + } - write () { - throw new TypeError('this is a readable stream') - } + this[_handle] = new realZlib[mode](opts) - end () { - throw new TypeError('this is a readable stream') - } - - [_open] () { - fs.open(this[_path], 'r', (er, fd) => this[_onopen](er, fd)) - } + this[_onError] = (err) => { + // there is no way to cleanly recover. + // continuing only obscures problems. + this.close() - [_onopen] (er, fd) { - if (er) - this[_onerror](er) - else { - this[_fd] = fd - this.emit('open', fd) - this[_read]() + const error = new ZlibError(err.message, err.errno) + this.emit('error', error) } - } + this[_handle].on('error', this[_onError]) - [_makeBuf] () { - return Buffer.allocUnsafe(Math.min(this[_readSize], this[_remain])) - } + const level = typeof opts.level === 'number' ? opts.level + : constants.Z_DEFAULT_COMPRESSION - [_read] () { - if (!this[_reading]) { - this[_reading] = true - const buf = this[_makeBuf]() - /* istanbul ignore if */ - if (buf.length === 0) return process.nextTick(() => this[_onread](null, 0, buf)) - fs.read(this[_fd], buf, 0, buf.length, null, (er, br, buf) => - this[_onread](er, br, buf)) - } - } + var strategy = typeof opts.strategy === 'number' ? opts.strategy + : constants.Z_DEFAULT_STRATEGY - [_onread] (er, br, buf) { - this[_reading] = false - if (er) - this[_onerror](er) - else if (this[_handleChunk](br, buf)) - this[_read]() - } + // API changed in node v9 + /* istanbul ignore next */ - [_close] () { - if (this[_autoClose] && typeof this[_fd] === 'number') { - fs.close(this[_fd], _ => this.emit('close')) - this[_fd] = null - } - } + this[_level] = level + this[_strategy] = strategy - [_onerror] (er) { - this[_reading] = true - this[_close]() - this.emit('error', er) + this.once('end', this.close) } - [_handleChunk] (br, buf) { - let ret = false - // no effect if infinite - this[_remain] -= br - if (br > 0) - ret = super.write(br < buf.length ? buf.slice(0, br) : buf) - - if (br === 0 || this[_remain] <= 0) { - ret = false - this[_close]() - super.end() + close () { + if (this[_handle]) { + this[_handle].close() + this[_handle] = null + this.emit('close') } - - return ret } - emit (ev, data) { - switch (ev) { - case 'prefinish': - case 'finish': - break + params (level, strategy) { + if (!this[_handle]) + throw new Error('cannot switch params when binding is closed') - case 'drain': - if (typeof this[_fd] === 'number') - this[_read]() - break + // no way to test this without also not supporting params at all + /* istanbul ignore if */ + if (!this[_handle].params) + throw new Error('not supported in this implementation') - default: - return super.emit(ev, data) + if (level < constants.Z_MIN_LEVEL || + level > constants.Z_MAX_LEVEL) { + throw new RangeError('Invalid compression level: ' + level) } - } -} -class ReadStreamSync extends ReadStream { - [_open] () { - let threw = true - try { - this[_onopen](null, fs.openSync(this[_path], 'r')) - threw = false - } finally { - if (threw) - this[_close]() - } - } + if (!(strategies.has(strategy))) + throw new TypeError('Invalid strategy: ' + strategy) - [_read] () { - let threw = true - try { - if (!this[_reading]) { - this[_reading] = true - do { - const buf = this[_makeBuf]() - /* istanbul ignore next */ - const br = buf.length === 0 ? 0 : fs.readSync(this[_fd], buf, 0, buf.length, null) - if (!this[_handleChunk](br, buf)) - break - } while (true) - this[_reading] = false + if (this[_level] !== level || this[_strategy] !== strategy) { + this.flush(constants.Z_SYNC_FLUSH) + assert(this[_handle], 'zlib binding closed') + // .params() calls .flush(), but the latter is always async in the + // core zlib. We override .flush() temporarily to intercept that and + // flush synchronously. + const origFlush = this[_handle].flush + this[_handle].flush = (flushFlag, cb) => { + this[_handle].flush = origFlush + this.flush(flushFlag) + cb() + } + this[_handle].params(level, strategy) + /* istanbul ignore else */ + if (this[_handle]) { + this[_level] = level + this[_strategy] = strategy } - threw = false - } finally { - if (threw) - this[_close]() } } - [_close] () { - if (this[_autoClose] && typeof this[_fd] === 'number') { - try { - fs.closeSync(this[_fd]) - } catch (er) {} - this[_fd] = null - this.emit('close') - } + reset () { + assert(this[_handle], 'zlib binding closed') + return this[_handle].reset() } -} - -class WriteStream extends EE { - constructor (path, opt) { - opt = opt || {} - super(opt) - this.readable = false - this[_writing] = false - this[_ended] = false - this[_needDrain] = false - this[_queue] = [] - this[_path] = path - this[_fd] = typeof opt.fd === 'number' ? opt.fd : null - this[_mode] = opt.mode === undefined ? 0o666 : opt.mode - this[_pos] = typeof opt.start === 'number' ? opt.start : null - this[_autoClose] = typeof opt.autoClose === 'boolean' ? - opt.autoClose : true - - // truncating makes no sense when writing into the middle - const defaultFlag = this[_pos] !== null ? 'r+' : 'w' - this[_defaultFlag] = opt.flags === undefined - this[_flags] = this[_defaultFlag] ? defaultFlag : opt.flags - if (this[_fd] === null) - this[_open]() - } + flush (kind) { + if (kind === undefined) + kind = constants.Z_FULL_FLUSH - get fd () { return this[_fd] } - get path () { return this[_path] } + if (this.ended) + return - [_onerror] (er) { - this[_close]() - this[_writing] = true - this.emit('error', er) + const flushFlag = this[_flushFlag] + this[_flushFlag] = kind + this.write(Buffer.alloc(0)) + this[_flushFlag] = flushFlag } - [_open] () { - fs.open(this[_path], this[_flags], this[_mode], - (er, fd) => this[_onopen](er, fd)) + end (chunk, encoding, cb) { + if (chunk) + this.write(chunk, encoding) + this.flush(this[_finishFlush]) + this[_ended] = true + return super.end(null, null, cb) } - [_onopen] (er, fd) { - if (this[_defaultFlag] && - this[_flags] === 'r+' && - er && er.code === 'ENOENT') { - this[_flags] = 'w' - this[_open]() - } else if (er) - this[_onerror](er) - else { - this[_fd] = fd - this.emit('open', fd) - this[_flush]() - } + get ended () { + return this[_ended] } - end (buf, enc) { - if (buf) - this.write(buf, enc) - - this[_ended] = true + write (chunk, encoding, cb) { + // process the chunk using the sync process + // then super.write() all the outputted chunks + if (typeof encoding === 'function') + cb = encoding, encoding = 'utf8' - // synthetic after-write logic, where drain/finish live - if (!this[_writing] && !this[_queue].length && - typeof this[_fd] === 'number') - this[_onwrite](null, 0) - } + if (typeof chunk === 'string') + chunk = Buffer.from(chunk, encoding) - write (buf, enc) { - if (typeof buf === 'string') - buf = new Buffer(buf, enc) + assert(this[_handle], 'zlib binding closed') - if (this[_ended]) { - this.emit('error', new Error('write() after end()')) - return false + // _processChunk tries to .close() the native handle after it's done, so we + // intercept that by temporarily making it a no-op. + const nativeHandle = this[_handle]._handle + const originalNativeClose = nativeHandle.close + nativeHandle.close = () => {} + const originalClose = this[_handle].close + this[_handle].close = () => {} + // It also calls `Buffer.concat()` at the end, which may be convenient + // for some, but which we are not interested in as it slows us down. + Buffer.concat = (args) => args + let result + try { + result = this[_handle]._processChunk(chunk, this[_flushFlag]) + } catch (err) { + this[_onError](err) + } finally { + Buffer.concat = OriginalBufferConcat + if (this[_handle]) { + // Core zlib resets `_handle` to null after attempting to close the + // native handle. Our no-op handler prevented actual closure, but we + // need to restore the `._handle` property. + this[_handle]._handle = nativeHandle + nativeHandle.close = originalNativeClose + this[_handle].close = originalClose + // `_processChunk()` adds an 'error' listener. If we don't remove it + // after each call, these handlers start piling up. + this[_handle].removeAllListeners('error') + } } - if (this[_fd] === null || this[_writing] || this[_queue].length) { - this[_queue].push(buf) - this[_needDrain] = true - return false + let writeReturn + if (result) { + if (Array.isArray(result) && result.length > 0) { + // The first buffer is always `handle._outBuffer`, which would be + // re-used for later invocations; so, we always have to copy that one. + writeReturn = super.write(Buffer.from(result[0])) + for (let i = 1; i < result.length; i++) { + writeReturn = super.write(result[i]) + } + } else { + writeReturn = super.write(Buffer.from(result)) + } } - this[_writing] = true - this[_write](buf) - return true + if (cb) + cb() + return writeReturn } +} - [_write] (buf) { - fs.write(this[_fd], buf, 0, buf.length, this[_pos], (er, bw) => - this[_onwrite](er, bw)) +// minimal 2-byte header +class Deflate extends Zlib { + constructor (opts) { + super(opts, 'Deflate') } +} - [_onwrite] (er, bw) { - if (er) - this[_onerror](er) - else { - if (this[_pos] !== null) - this[_pos] += bw - if (this[_queue].length) - this[_flush]() - else { - this[_writing] = false - - if (this[_ended] && !this[_finished]) { - this[_finished] = true - this[_close]() - this.emit('finish') - } else if (this[_needDrain]) { - this[_needDrain] = false - this.emit('drain') - } - } - } +class Inflate extends Zlib { + constructor (opts) { + super(opts, 'Inflate') } +} - [_flush] () { - if (this[_queue].length === 0) { - if (this[_ended]) - this[_onwrite](null, 0) - } else if (this[_queue].length === 1) - this[_write](this[_queue].pop()) - else { - const iovec = this[_queue] - this[_queue] = [] - writev(this[_fd], iovec, this[_pos], - (er, bw) => this[_onwrite](er, bw)) - } +// gzip - bigger header, same deflate compression +class Gzip extends Zlib { + constructor (opts) { + super(opts, 'Gzip') } +} - [_close] () { - if (this[_autoClose] && typeof this[_fd] === 'number') { - fs.close(this[_fd], _ => this.emit('close')) - this[_fd] = null - } +class Gunzip extends Zlib { + constructor (opts) { + super(opts, 'Gunzip') } } -class WriteStreamSync extends WriteStream { - [_open] () { - let fd - try { - fd = fs.openSync(this[_path], this[_flags], this[_mode]) - } catch (er) { - if (this[_defaultFlag] && - this[_flags] === 'r+' && - er && er.code === 'ENOENT') { - this[_flags] = 'w' - return this[_open]() - } else - throw er - } - this[_onopen](null, fd) +// raw - no header +class DeflateRaw extends Zlib { + constructor (opts) { + super(opts, 'DeflateRaw') } +} - [_close] () { - if (this[_autoClose] && typeof this[_fd] === 'number') { - try { - fs.closeSync(this[_fd]) - } catch (er) {} - this[_fd] = null - this.emit('close') - } +class InflateRaw extends Zlib { + constructor (opts) { + super(opts, 'InflateRaw') } +} - [_write] (buf) { - try { - this[_onwrite](null, - fs.writeSync(this[_fd], buf, 0, buf.length, this[_pos])) - } catch (er) { - this[_onwrite](er, 0) - } +// auto-detect header. +class Unzip extends Zlib { + constructor (opts) { + super(opts, 'Unzip') } } -const writev = (fd, iovec, pos, cb) => { - const done = (er, bw) => cb(er, bw, iovec) - const req = new FSReqWrap() - req.oncomplete = done - binding.writeBuffers(fd, iovec, pos, req) -} +exports.Deflate = Deflate +exports.Inflate = Inflate +exports.Gzip = Gzip +exports.Gunzip = Gunzip +exports.DeflateRaw = DeflateRaw +exports.InflateRaw = InflateRaw +exports.Unzip = Unzip -exports.ReadStream = ReadStream -exports.ReadStreamSync = ReadStreamSync -exports.WriteStream = WriteStream -exports.WriteStreamSync = WriteStreamSync +/***/ }), +/* 290 */ +/***/ (function(module, exports) { + +module.exports = Object.freeze({ + Z_NO_FLUSH: 0, + Z_PARTIAL_FLUSH: 1, + Z_SYNC_FLUSH: 2, + Z_FULL_FLUSH: 3, + Z_FINISH: 4, + Z_BLOCK: 5, + Z_OK: 0, + Z_STREAM_END: 1, + Z_NEED_DICT: 2, + Z_ERRNO: -1, + Z_STREAM_ERROR: -2, + Z_DATA_ERROR: -3, + Z_MEM_ERROR: -4, + Z_BUF_ERROR: -5, + Z_VERSION_ERROR: -6, + Z_NO_COMPRESSION: 0, + Z_BEST_SPEED: 1, + Z_BEST_COMPRESSION: 9, + Z_DEFAULT_COMPRESSION: -1, + Z_FILTERED: 1, + Z_HUFFMAN_ONLY: 2, + Z_RLE: 3, + Z_FIXED: 4, + Z_DEFAULT_STRATEGY: 0, + ZLIB_VERNUM: 4736, + DEFLATE: 1, + INFLATE: 2, + GZIP: 3, + GUNZIP: 4, + DEFLATERAW: 5, + INFLATERAW: 6, + UNZIP: 7, + Z_MIN_WINDOWBITS: 8, + Z_MAX_WINDOWBITS: 15, + Z_DEFAULT_WINDOWBITS: 15, + Z_MIN_CHUNK: 64, + Z_MAX_CHUNK: Infinity, + Z_DEFAULT_CHUNK: 16384, + Z_MIN_MEMLEVEL: 1, + Z_MAX_MEMLEVEL: 9, + Z_DEFAULT_MEMLEVEL: 8, + Z_MIN_LEVEL: -1, + Z_MAX_LEVEL: 9, + Z_DEFAULT_LEVEL: -1 +}) /***/ }), -/* 299 */ +/* 291 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const types = __webpack_require__(292) +const MiniPass = __webpack_require__(285) -const Buffer = __webpack_require__(280) +const SLURP = Symbol('slurp') +module.exports = class ReadEntry extends MiniPass { + constructor (header, ex, gex) { + super() + this.extended = ex + this.globalExtended = gex + this.header = header + this.startBlockSize = 512 * Math.ceil(header.size / 512) + this.blockRemain = this.startBlockSize + this.remain = header.size + this.type = header.type + this.meta = false + this.ignore = false + switch (this.type) { + case 'File': + case 'OldFile': + case 'Link': + case 'SymbolicLink': + case 'CharacterDevice': + case 'BlockDevice': + case 'Directory': + case 'FIFO': + case 'ContiguousFile': + case 'GNUDumpDir': + break -// XXX: This shares a lot in common with extract.js -// maybe some DRY opportunity here? + case 'NextFileHasLongLinkpath': + case 'NextFileHasLongPath': + case 'OldGnuLongPath': + case 'GlobalExtendedHeader': + case 'ExtendedHeader': + case 'OldExtendedHeader': + this.meta = true + break -// tar -t -const hlo = __webpack_require__(278) -const Parser = __webpack_require__(300) -const fs = __webpack_require__(4) -const fsm = __webpack_require__(298) -const path = __webpack_require__(20) + // NOTE: gnutar and bsdtar treat unrecognized types as 'File' + // it may be worth doing the same, but with a warning. + default: + this.ignore = true + } -const t = module.exports = (opt_, files, cb) => { - if (typeof opt_ === 'function') - cb = opt_, files = null, opt_ = {} - else if (Array.isArray(opt_)) - files = opt_, opt_ = {} - - if (typeof files === 'function') - cb = files, files = null - - if (!files) - files = [] - else - files = Array.from(files) - - const opt = hlo(opt_) - - if (opt.sync && typeof cb === 'function') - throw new TypeError('callback not supported for sync tar functions') - - if (!opt.file && typeof cb === 'function') - throw new TypeError('callback only supported with file option') - - if (files.length) - filesFilter(opt, files) - - if (!opt.noResume) - onentryFunction(opt) + this.path = header.path + this.mode = header.mode + if (this.mode) + this.mode = this.mode & 0o7777 + this.uid = header.uid + this.gid = header.gid + this.uname = header.uname + this.gname = header.gname + this.size = header.size + this.mtime = header.mtime + this.atime = header.atime + this.ctime = header.ctime + this.linkpath = header.linkpath + this.uname = header.uname + this.gname = header.gname - return opt.file && opt.sync ? listFileSync(opt) - : opt.file ? listFile(opt, cb) - : list(opt) -} + if (ex) this[SLURP](ex) + if (gex) this[SLURP](gex, true) + } -const onentryFunction = opt => { - const onentry = opt.onentry - opt.onentry = onentry ? e => { - onentry(e) - e.resume() - } : e => e.resume() -} + write (data) { + const writeLen = data.length + if (writeLen > this.blockRemain) + throw new Error('writing more to entry than is appropriate') -// construct a filter that limits the file entries listed -// include child entries if a dir is included -const filesFilter = (opt, files) => { - const map = new Map(files.map(f => [f.replace(/\/+$/, ''), true])) - const filter = opt.filter + const r = this.remain + const br = this.blockRemain + this.remain = Math.max(0, r - writeLen) + this.blockRemain = Math.max(0, br - writeLen) + if (this.ignore) + return true - const mapHas = (file, r) => { - const root = r || path.parse(file).root || '.' - const ret = file === root ? false - : map.has(file) ? map.get(file) - : mapHas(path.dirname(file), root) + if (r >= writeLen) + return super.write(data) - map.set(file, ret) - return ret + // r < writeLen + return super.write(data.slice(0, r)) } - opt.filter = filter - ? (file, entry) => filter(file, entry) && mapHas(file.replace(/\/+$/, '')) - : file => mapHas(file.replace(/\/+$/, '')) -} - -const listFileSync = opt => { - const p = list(opt) - const file = opt.file - let threw = true - let fd - try { - const stat = fs.statSync(file) - const readSize = opt.maxReadSize || 16*1024*1024 - if (stat.size < readSize) { - p.end(fs.readFileSync(file)) - } else { - let pos = 0 - const buf = Buffer.allocUnsafe(readSize) - fd = fs.openSync(file, 'r') - while (pos < stat.size) { - let bytesRead = fs.readSync(fd, buf, 0, readSize, pos) - pos += bytesRead - p.write(buf.slice(0, bytesRead)) - } - p.end() + [SLURP] (ex, global) { + for (let k in ex) { + // we slurp in everything except for the path attribute in + // a global extended header, because that's weird. + if (ex[k] !== null && ex[k] !== undefined && + !(global && k === 'path')) + this[k] = ex[k] } - threw = false - } finally { - if (threw && fd) - try { fs.closeSync(fd) } catch (er) {} } } -const listFile = (opt, cb) => { - const parse = new Parser(opt) - const readSize = opt.maxReadSize || 16*1024*1024 - const file = opt.file - const p = new Promise((resolve, reject) => { - parse.on('error', reject) - parse.on('end', resolve) +/***/ }), +/* 292 */ +/***/ (function(module, exports, __webpack_require__) { - fs.stat(file, (er, stat) => { - if (er) - reject(er) - else { - const stream = new fsm.ReadStream(file, { - readSize: readSize, - size: stat.size - }) - stream.on('error', reject) - stream.pipe(parse) - } - }) - }) - return cb ? p.then(cb, cb) : p -} +"use strict"; -const list = opt => new Parser(opt) +// map types from key to human-friendly name +exports.name = new Map([ + ['0', 'File'], + // same as File + ['', 'OldFile'], + ['1', 'Link'], + ['2', 'SymbolicLink'], + // Devices and FIFOs aren't fully supported + // they are parsed, but skipped when unpacking + ['3', 'CharacterDevice'], + ['4', 'BlockDevice'], + ['5', 'Directory'], + ['6', 'FIFO'], + // same as File + ['7', 'ContiguousFile'], + // pax headers + ['g', 'GlobalExtendedHeader'], + ['x', 'ExtendedHeader'], + // vendor-specific stuff + // skip + ['A', 'SolarisACL'], + // like 5, but with data, which should be skipped + ['D', 'GNUDumpDir'], + // metadata only, skip + ['I', 'Inode'], + // data = link path of next file + ['K', 'NextFileHasLongLinkpath'], + // data = path of next file + ['L', 'NextFileHasLongPath'], + // skip + ['M', 'ContinuationFile'], + // like L + ['N', 'OldGnuLongPath'], + // skip + ['S', 'SparseFile'], + // skip + ['V', 'TapeVolumeHeader'], + // like x + ['X', 'OldExtendedHeader'] +]) + +// map the other direction +exports.code = new Map(Array.from(exports.name).map(kv => [kv[1], kv[0]])) /***/ }), -/* 300 */ +/* 293 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; - -// this[BUFFER] is the remainder of a chunk if we're waiting for -// the full 512 bytes of a header to come in. We will Buffer.concat() -// it to the next write(), which is a mem copy, but a small one. -// -// this[QUEUE] is a Yallist of entries that haven't been emitted -// yet this can only get filled up if the user keeps write()ing after -// a write() returns false, or does a write() with more than one entry -// -// We don't buffer chunks, we always parse them and either create an -// entry, or push it into the active entry. The ReadEntry class knows -// to throw data away if .ignore=true -// -// Shift entry off the buffer when it emits 'end', and emit 'entry' for -// the next one in the list. -// -// At any time, we're pushing body chunks into the entry at WRITEENTRY, -// and waiting for 'end' on the entry at READENTRY -// -// ignored entries get .resume() called on them straight away - -const warner = __webpack_require__(295) +const Buffer = __webpack_require__(282) +const MiniPass = __webpack_require__(285) +const Pax = __webpack_require__(294) +const Header = __webpack_require__(295) +const ReadEntry = __webpack_require__(291) +const fs = __webpack_require__(4) const path = __webpack_require__(20) -const Header = __webpack_require__(293) -const EE = __webpack_require__(137) -const Yallist = __webpack_require__(284) -const maxMetaEntrySize = 1024 * 1024 -const Entry = __webpack_require__(289) -const Pax = __webpack_require__(292) -const zlib = __webpack_require__(287) -const Buffer = __webpack_require__(280) -const gzipHeader = Buffer.from([0x1f, 0x8b]) -const STATE = Symbol('state') -const WRITEENTRY = Symbol('writeEntry') -const READENTRY = Symbol('readEntry') -const NEXTENTRY = Symbol('nextEntry') -const PROCESSENTRY = Symbol('processEntry') -const EX = Symbol('extendedHeader') -const GEX = Symbol('globalExtendedHeader') -const META = Symbol('meta') -const EMITMETA = Symbol('emitMeta') -const BUFFER = Symbol('buffer') -const QUEUE = Symbol('queue') -const ENDED = Symbol('ended') -const EMITTEDEND = Symbol('emittedEnd') -const EMIT = Symbol('emit') -const UNZIP = Symbol('unzip') -const CONSUMECHUNK = Symbol('consumeChunk') -const CONSUMECHUNKSUB = Symbol('consumeChunkSub') -const CONSUMEBODY = Symbol('consumeBody') -const CONSUMEMETA = Symbol('consumeMeta') -const CONSUMEHEADER = Symbol('consumeHeader') -const CONSUMING = Symbol('consuming') -const BUFFERCONCAT = Symbol('bufferConcat') -const MAYBEEND = Symbol('maybeEnd') -const WRITING = Symbol('writing') -const ABORTED = Symbol('aborted') -const DONE = Symbol('onDone') +const types = __webpack_require__(292) +const maxReadSize = 16 * 1024 * 1024 +const PROCESS = Symbol('process') +const FILE = Symbol('file') +const DIRECTORY = Symbol('directory') +const SYMLINK = Symbol('symlink') +const HARDLINK = Symbol('hardlink') +const HEADER = Symbol('header') +const READ = Symbol('read') +const LSTAT = Symbol('lstat') +const ONLSTAT = Symbol('onlstat') +const ONREAD = Symbol('onread') +const ONREADLINK = Symbol('onreadlink') +const OPENFILE = Symbol('openfile') +const ONOPENFILE = Symbol('onopenfile') +const CLOSE = Symbol('close') +const MODE = Symbol('mode') +const warner = __webpack_require__(297) +const winchars = __webpack_require__(298) -const noop = _ => true +const modeFix = __webpack_require__(299) -module.exports = warner(class Parser extends EE { - constructor (opt) { +const WriteEntry = warner(class WriteEntry extends MiniPass { + constructor (p, opt) { opt = opt || {} super(opt) - - if (opt.ondone) - this.on(DONE, opt.ondone) - else - this.on(DONE, _ => { - this.emit('prefinish') - this.emit('finish') - this.emit('end') - this.emit('close') - }) - + if (typeof p !== 'string') + throw new TypeError('path is required') + this.path = p + // suppress atime, ctime, uid, gid, uname, gname + this.portable = !!opt.portable + // until node has builtin pwnam functions, this'll have to do + this.myuid = process.getuid && process.getuid() + this.myuser = process.env.USER || '' + this.maxReadSize = opt.maxReadSize || maxReadSize + this.linkCache = opt.linkCache || new Map() + this.statCache = opt.statCache || new Map() + this.preservePaths = !!opt.preservePaths + this.cwd = opt.cwd || process.cwd() this.strict = !!opt.strict - this.maxMetaEntrySize = opt.maxMetaEntrySize || maxMetaEntrySize - this.filter = typeof opt.filter === 'function' ? opt.filter : noop - - // have to set this so that streams are ok piping into it - this.writable = true - this.readable = false + this.noPax = !!opt.noPax + this.noMtime = !!opt.noMtime + this.mtime = opt.mtime || null - this[QUEUE] = new Yallist() - this[BUFFER] = null - this[READENTRY] = null - this[WRITEENTRY] = null - this[STATE] = 'begin' - this[META] = '' - this[EX] = null - this[GEX] = null - this[ENDED] = false - this[UNZIP] = null - this[ABORTED] = false if (typeof opt.onwarn === 'function') this.on('warn', opt.onwarn) - if (typeof opt.onentry === 'function') - this.on('entry', opt.onentry) - } - - [CONSUMEHEADER] (chunk, position) { - const header = new Header(chunk, position, this[EX], this[GEX]) - - if (header.nullBlock) - this[EMIT]('nullBlock') - else if (!header.cksumValid) - this.warn('invalid entry', header) - else if (!header.path) - this.warn('invalid: path is required', header) - else { - const type = header.type - if (/^(Symbolic)?Link$/.test(type) && !header.linkpath) - this.warn('invalid: linkpath required', header) - else if (!/^(Symbolic)?Link$/.test(type) && header.linkpath) - this.warn('invalid: linkpath forbidden', header) - else { - const entry = this[WRITEENTRY] = new Entry(header, this[EX], this[GEX]) - - if (entry.meta) { - if (entry.size > this.maxMetaEntrySize) { - entry.ignore = true - this[EMIT]('ignoredEntry', entry) - this[STATE] = 'ignore' - } else if (entry.size > 0) { - this[META] = '' - entry.on('data', c => this[META] += c) - this[STATE] = 'meta' - } - } else { - - this[EX] = null - entry.ignore = entry.ignore || !this.filter(entry.path, entry) - if (entry.ignore) { - this[EMIT]('ignoredEntry', entry) - this[STATE] = entry.remain ? 'ignore' : 'begin' - } else { - if (entry.remain) - this[STATE] = 'body' - else { - this[STATE] = 'begin' - entry.end() - } - if (!this[READENTRY]) { - this[QUEUE].push(entry) - this[NEXTENTRY]() - } else - this[QUEUE].push(entry) - } - } - } + if (!this.preservePaths && path.win32.isAbsolute(p)) { + // absolutes on posix are also absolutes on win32 + // so we only need to test this one to get both + const parsed = path.win32.parse(p) + this.warn('stripping ' + parsed.root + ' from absolute path', p) + this.path = p.substr(parsed.root.length) } - } - - [PROCESSENTRY] (entry) { - let go = true - if (!entry) { - this[READENTRY] = null - go = false - } else if (Array.isArray(entry)) - this.emit.apply(this, entry) - else { - this[READENTRY] = entry - this.emit('entry', entry) - if (!entry.emittedEnd) { - entry.on('end', _ => this[NEXTENTRY]()) - go = false - } + this.win32 = !!opt.win32 || process.platform === 'win32' + if (this.win32) { + this.path = winchars.decode(this.path.replace(/\\/g, '/')) + p = p.replace(/\\/g, '/') } - return go - } + this.absolute = opt.absolute || path.resolve(this.cwd, p) - [NEXTENTRY] () { - do {} while (this[PROCESSENTRY](this[QUEUE].shift())) + if (this.path === '') + this.path = './' - if (!this[QUEUE].length) { - // At this point, there's nothing in the queue, but we may have an - // entry which is being consumed (readEntry). - // If we don't, then we definitely can handle more data. - // If we do, and either it's flowing, or it has never had any data - // written to it, then it needs more. - // The only other possibility is that it has returned false from a - // write() call, so we wait for the next drain to continue. - const re = this[READENTRY] - const drainNow = !re || re.flowing || re.size === re.remain - if (drainNow) { - if (!this[WRITING]) - this.emit('drain') - } else - re.once('drain', _ => this.emit('drain')) - } + if (this.statCache.has(this.absolute)) + this[ONLSTAT](this.statCache.get(this.absolute)) + else + this[LSTAT]() } - [CONSUMEBODY] (chunk, position) { - // write up to but no more than writeEntry.blockRemain - const entry = this[WRITEENTRY] - const br = entry.blockRemain - const c = (br >= chunk.length && position === 0) ? chunk - : chunk.slice(position, position + br) + [LSTAT] () { + fs.lstat(this.absolute, (er, stat) => { + if (er) + return this.emit('error', er) + this[ONLSTAT](stat) + }) + } - entry.write(c) + [ONLSTAT] (stat) { + this.statCache.set(this.absolute, stat) + this.stat = stat + if (!stat.isFile()) + stat.size = 0 + this.type = getType(stat) + this.emit('stat', stat) + this[PROCESS]() + } - if (!entry.blockRemain) { - this[STATE] = 'begin' - this[WRITEENTRY] = null - entry.end() + [PROCESS] () { + switch (this.type) { + case 'File': return this[FILE]() + case 'Directory': return this[DIRECTORY]() + case 'SymbolicLink': return this[SYMLINK]() + // unsupported types are ignored. + default: return this.end() } + } - return c.length + [MODE] (mode) { + return modeFix(mode, this.type === 'Directory') } - [CONSUMEMETA] (chunk, position) { - const entry = this[WRITEENTRY] - const ret = this[CONSUMEBODY](chunk, position) + [HEADER] () { + if (this.type === 'Directory' && this.portable) + this.noMtime = true - // if we finished, then the entry is reset - if (!this[WRITEENTRY]) - this[EMITMETA](entry) + this.header = new Header({ + path: this.path, + linkpath: this.linkpath, + // only the permissions and setuid/setgid/sticky bitflags + // not the higher-order bits that specify file type + mode: this[MODE](this.stat.mode), + uid: this.portable ? null : this.stat.uid, + gid: this.portable ? null : this.stat.gid, + size: this.stat.size, + mtime: this.noMtime ? null : this.mtime || this.stat.mtime, + type: this.type, + uname: this.portable ? null : + this.stat.uid === this.myuid ? this.myuser : '', + atime: this.portable ? null : this.stat.atime, + ctime: this.portable ? null : this.stat.ctime + }) - return ret + if (this.header.encode() && !this.noPax) + this.write(new Pax({ + atime: this.portable ? null : this.header.atime, + ctime: this.portable ? null : this.header.ctime, + gid: this.portable ? null : this.header.gid, + mtime: this.noMtime ? null : this.mtime || this.header.mtime, + path: this.path, + linkpath: this.linkpath, + size: this.header.size, + uid: this.portable ? null : this.header.uid, + uname: this.portable ? null : this.header.uname, + dev: this.portable ? null : this.stat.dev, + ino: this.portable ? null : this.stat.ino, + nlink: this.portable ? null : this.stat.nlink + }).encode()) + this.write(this.header.block) } - [EMIT] (ev, data, extra) { - if (!this[QUEUE].length && !this[READENTRY]) - this.emit(ev, data, extra) - else - this[QUEUE].push([ev, data, extra]) + [DIRECTORY] () { + if (this.path.substr(-1) !== '/') + this.path += '/' + this.stat.size = 0 + this[HEADER]() + this.end() } - [EMITMETA] (entry) { - this[EMIT]('meta', this[META]) - switch (entry.type) { - case 'ExtendedHeader': - case 'OldExtendedHeader': - this[EX] = Pax.parse(this[META], this[EX], false) - break - - case 'GlobalExtendedHeader': - this[GEX] = Pax.parse(this[META], this[GEX], true) - break - - case 'NextFileHasLongPath': - case 'OldGnuLongPath': - this[EX] = this[EX] || Object.create(null) - this[EX].path = this[META].replace(/\0.*/, '') - break - - case 'NextFileHasLongLinkpath': - this[EX] = this[EX] || Object.create(null) - this[EX].linkpath = this[META].replace(/\0.*/, '') - break - - /* istanbul ignore next */ - default: throw new Error('unknown meta: ' + entry.type) - } + [SYMLINK] () { + fs.readlink(this.absolute, (er, linkpath) => { + if (er) + return this.emit('error', er) + this[ONREADLINK](linkpath) + }) } - abort (msg, error) { - this[ABORTED] = true - this.warn(msg, error) - this.emit('abort', error) - this.emit('error', error) + [ONREADLINK] (linkpath) { + this.linkpath = linkpath + this[HEADER]() + this.end() } - write (chunk) { - if (this[ABORTED]) - return + [HARDLINK] (linkpath) { + this.type = 'Link' + this.linkpath = path.relative(this.cwd, linkpath) + this.stat.size = 0 + this[HEADER]() + this.end() + } - // first write, might be gzipped - if (this[UNZIP] === null && chunk) { - if (this[BUFFER]) { - chunk = Buffer.concat([this[BUFFER], chunk]) - this[BUFFER] = null - } - if (chunk.length < gzipHeader.length) { - this[BUFFER] = chunk - return true - } - for (let i = 0; this[UNZIP] === null && i < gzipHeader.length; i++) { - if (chunk[i] !== gzipHeader[i]) - this[UNZIP] = false - } - if (this[UNZIP] === null) { - const ended = this[ENDED] - this[ENDED] = false - this[UNZIP] = new zlib.Unzip() - this[UNZIP].on('data', chunk => this[CONSUMECHUNK](chunk)) - this[UNZIP].on('error', er => - this.abort(er.message, er)) - this[UNZIP].on('end', _ => { - this[ENDED] = true - this[CONSUMECHUNK]() - }) - this[WRITING] = true - const ret = this[UNZIP][ended ? 'end' : 'write' ](chunk) - this[WRITING] = false - return ret + [FILE] () { + if (this.stat.nlink > 1) { + const linkKey = this.stat.dev + ':' + this.stat.ino + if (this.linkCache.has(linkKey)) { + const linkpath = this.linkCache.get(linkKey) + if (linkpath.indexOf(this.cwd) === 0) + return this[HARDLINK](linkpath) } + this.linkCache.set(linkKey, this.absolute) } - this[WRITING] = true - if (this[UNZIP]) - this[UNZIP].write(chunk) - else - this[CONSUMECHUNK](chunk) - this[WRITING] = false - - // return false if there's a queue, or if the current entry isn't flowing - const ret = - this[QUEUE].length ? false : - this[READENTRY] ? this[READENTRY].flowing : - true - - // if we have no queue, then that means a clogged READENTRY - if (!ret && !this[QUEUE].length) - this[READENTRY].once('drain', _ => this.emit('drain')) + this[HEADER]() + if (this.stat.size === 0) + return this.end() - return ret + this[OPENFILE]() } - [BUFFERCONCAT] (c) { - if (c && !this[ABORTED]) - this[BUFFER] = this[BUFFER] ? Buffer.concat([this[BUFFER], c]) : c + [OPENFILE] () { + fs.open(this.absolute, 'r', (er, fd) => { + if (er) + return this.emit('error', er) + this[ONOPENFILE](fd) + }) } - [MAYBEEND] () { - if (this[ENDED] && - !this[EMITTEDEND] && - !this[ABORTED] && - !this[CONSUMING]) { - this[EMITTEDEND] = true - const entry = this[WRITEENTRY] - if (entry && entry.blockRemain) { - const have = this[BUFFER] ? this[BUFFER].length : 0 - this.warn('Truncated input (needed ' + entry.blockRemain + - ' more bytes, only ' + have + ' available)', entry) - if (this[BUFFER]) - entry.write(this[BUFFER]) - entry.end() - } - this[EMIT](DONE) - } + [ONOPENFILE] (fd) { + const blockLen = 512 * Math.ceil(this.stat.size / 512) + const bufLen = Math.min(blockLen, this.maxReadSize) + const buf = Buffer.allocUnsafe(bufLen) + this[READ](fd, buf, 0, buf.length, 0, this.stat.size, blockLen) } - [CONSUMECHUNK] (chunk) { - if (this[CONSUMING]) { - this[BUFFERCONCAT](chunk) - } else if (!chunk && !this[BUFFER]) { - this[MAYBEEND]() - } else { - this[CONSUMING] = true - if (this[BUFFER]) { - this[BUFFERCONCAT](chunk) - const c = this[BUFFER] - this[BUFFER] = null - this[CONSUMECHUNKSUB](c) - } else { - this[CONSUMECHUNKSUB](chunk) - } - - while (this[BUFFER] && this[BUFFER].length >= 512 && !this[ABORTED]) { - const c = this[BUFFER] - this[BUFFER] = null - this[CONSUMECHUNKSUB](c) - } - this[CONSUMING] = false - } - - if (!this[BUFFER] || this[ENDED]) - this[MAYBEEND]() + [READ] (fd, buf, offset, length, pos, remain, blockRemain) { + fs.read(fd, buf, offset, length, pos, (er, bytesRead) => { + if (er) + return this[CLOSE](fd, _ => this.emit('error', er)) + this[ONREAD](fd, buf, offset, length, pos, remain, blockRemain, bytesRead) + }) } - [CONSUMECHUNKSUB] (chunk) { - // we know that we are in CONSUMING mode, so anything written goes into - // the buffer. Advance the position and put any remainder in the buffer. - let position = 0 - let length = chunk.length - while (position + 512 <= length && !this[ABORTED]) { - switch (this[STATE]) { - case 'begin': - this[CONSUMEHEADER](chunk, position) - position += 512 - break - - case 'ignore': - case 'body': - position += this[CONSUMEBODY](chunk, position) - break - - case 'meta': - position += this[CONSUMEMETA](chunk, position) - break + [CLOSE] (fd, cb) { + fs.close(fd, cb) + } - /* istanbul ignore next */ - default: - throw new Error('invalid state: ' + this[STATE]) - } + [ONREAD] (fd, buf, offset, length, pos, remain, blockRemain, bytesRead) { + if (bytesRead <= 0 && remain > 0) { + const er = new Error('encountered unexpected EOF') + er.path = this.absolute + er.syscall = 'read' + er.code = 'EOF' + this[CLOSE](fd) + return this.emit('error', er) } - if (position < length) { - if (this[BUFFER]) - this[BUFFER] = Buffer.concat([chunk.slice(position), this[BUFFER]]) - else - this[BUFFER] = chunk.slice(position) + if (bytesRead > remain) { + const er = new Error('did not encounter expected EOF') + er.path = this.absolute + er.syscall = 'read' + er.code = 'EOF' + this[CLOSE](fd) + return this.emit('error', er) } - } - end (chunk) { - if (!this[ABORTED]) { - if (this[UNZIP]) - this[UNZIP].end(chunk) - else { - this[ENDED] = true - this.write(chunk) + // null out the rest of the buffer, if we could fit the block padding + if (bytesRead === remain) { + for (let i = bytesRead; i < length && bytesRead < blockRemain; i++) { + buf[i + offset] = 0 + bytesRead ++ + remain ++ } } - } -}) - -/***/ }), -/* 301 */ -/***/ (function(module, exports, __webpack_require__) { + const writeBuf = offset === 0 && bytesRead === buf.length ? + buf : buf.slice(offset, offset + bytesRead) + remain -= bytesRead + blockRemain -= bytesRead + pos += bytesRead + offset += bytesRead -"use strict"; + this.write(writeBuf) -const Buffer = __webpack_require__(280) + if (!remain) { + if (blockRemain) + this.write(Buffer.alloc(blockRemain)) + this.end() + this[CLOSE](fd, _ => _) + return + } -// tar -r -const hlo = __webpack_require__(278) -const Pack = __webpack_require__(279) -const Parse = __webpack_require__(300) -const fs = __webpack_require__(4) -const fsm = __webpack_require__(298) -const t = __webpack_require__(299) -const path = __webpack_require__(20) + if (offset >= length) { + buf = Buffer.allocUnsafe(length) + offset = 0 + } + length = buf.length - offset + this[READ](fd, buf, offset, length, pos, remain, blockRemain) + } +}) -// starting at the head of the file, read a Header -// If the checksum is invalid, that's our position to start writing -// If it is, jump forward by the specified size (round up to 512) -// and try again. -// Write the new Pack stream starting there. +class WriteEntrySync extends WriteEntry { + constructor (path, opt) { + super(path, opt) + } -const Header = __webpack_require__(293) + [LSTAT] () { + this[ONLSTAT](fs.lstatSync(this.absolute)) + } -const r = module.exports = (opt_, files, cb) => { - const opt = hlo(opt_) + [SYMLINK] () { + this[ONREADLINK](fs.readlinkSync(this.absolute)) + } - if (!opt.file) - throw new TypeError('file is required') + [OPENFILE] () { + this[ONOPENFILE](fs.openSync(this.absolute, 'r')) + } - if (opt.gzip) - throw new TypeError('cannot append to compressed archives') + [READ] (fd, buf, offset, length, pos, remain, blockRemain) { + let threw = true + try { + const bytesRead = fs.readSync(fd, buf, offset, length, pos) + this[ONREAD](fd, buf, offset, length, pos, remain, blockRemain, bytesRead) + threw = false + } finally { + if (threw) + try { this[CLOSE](fd) } catch (er) {} + } + } - if (!files || !Array.isArray(files) || !files.length) - throw new TypeError('no files or directories specified') + [CLOSE] (fd) { + fs.closeSync(fd) + } +} - files = Array.from(files) +const WriteEntryTar = warner(class WriteEntryTar extends MiniPass { + constructor (readEntry, opt) { + opt = opt || {} + super(opt) + this.preservePaths = !!opt.preservePaths + this.portable = !!opt.portable + this.strict = !!opt.strict + this.noPax = !!opt.noPax + this.noMtime = !!opt.noMtime - return opt.sync ? replaceSync(opt, files) - : replace(opt, files, cb) -} + this.readEntry = readEntry + this.type = readEntry.type + if (this.type === 'Directory' && this.portable) + this.noMtime = true -const replaceSync = (opt, files) => { - const p = new Pack.Sync(opt) + this.path = readEntry.path + this.mode = this[MODE](readEntry.mode) + this.uid = this.portable ? null : readEntry.uid + this.gid = this.portable ? null : readEntry.gid + this.uname = this.portable ? null : readEntry.uname + this.gname = this.portable ? null : readEntry.gname + this.size = readEntry.size + this.mtime = this.noMtime ? null : opt.mtime || readEntry.mtime + this.atime = this.portable ? null : readEntry.atime + this.ctime = this.portable ? null : readEntry.ctime + this.linkpath = readEntry.linkpath - let threw = true - let fd - let position + if (typeof opt.onwarn === 'function') + this.on('warn', opt.onwarn) - try { - try { - fd = fs.openSync(opt.file, 'r+') - } catch (er) { - if (er.code === 'ENOENT') - fd = fs.openSync(opt.file, 'w+') - else - throw er + if (path.isAbsolute(this.path) && !this.preservePaths) { + const parsed = path.parse(this.path) + this.warn( + 'stripping ' + parsed.root + ' from absolute path', + this.path + ) + this.path = this.path.substr(parsed.root.length) } - const st = fs.fstatSync(fd) - const headBuf = Buffer.alloc(512) + this.remain = readEntry.size + this.blockRemain = readEntry.startBlockSize - POSITION: for (position = 0; position < st.size; position += 512) { - for (let bufPos = 0, bytes = 0; bufPos < 512; bufPos += bytes) { - bytes = fs.readSync( - fd, headBuf, bufPos, headBuf.length - bufPos, position + bufPos - ) + this.header = new Header({ + path: this.path, + linkpath: this.linkpath, + // only the permissions and setuid/setgid/sticky bitflags + // not the higher-order bits that specify file type + mode: this.mode, + uid: this.portable ? null : this.uid, + gid: this.portable ? null : this.gid, + size: this.size, + mtime: this.noMtime ? null : this.mtime, + type: this.type, + uname: this.portable ? null : this.uname, + atime: this.portable ? null : this.atime, + ctime: this.portable ? null : this.ctime + }) - if (position === 0 && headBuf[0] === 0x1f && headBuf[1] === 0x8b) - throw new Error('cannot append to compressed archives') + if (this.header.encode() && !this.noPax) + super.write(new Pax({ + atime: this.portable ? null : this.atime, + ctime: this.portable ? null : this.ctime, + gid: this.portable ? null : this.gid, + mtime: this.noMtime ? null : this.mtime, + path: this.path, + linkpath: this.linkpath, + size: this.size, + uid: this.portable ? null : this.uid, + uname: this.portable ? null : this.uname, + dev: this.portable ? null : this.readEntry.dev, + ino: this.portable ? null : this.readEntry.ino, + nlink: this.portable ? null : this.readEntry.nlink + }).encode()) - if (!bytes) - break POSITION - } + super.write(this.header.block) + readEntry.pipe(this) + } - let h = new Header(headBuf) - if (!h.cksumValid) - break - let entryBlockSize = 512 * Math.ceil(h.size / 512) - if (position + entryBlockSize + 512 > st.size) - break - // the 512 for the header we just parsed will be added as well - // also jump ahead all the blocks for the body - position += entryBlockSize - if (opt.mtimeCache) - opt.mtimeCache.set(h.path, h.mtime) - } - threw = false + [MODE] (mode) { + return modeFix(mode, this.type === 'Directory') + } - streamSync(opt, p, position, fd, files) - } finally { - if (threw) - try { fs.closeSync(fd) } catch (er) {} + write (data) { + const writeLen = data.length + if (writeLen > this.blockRemain) + throw new Error('writing more to entry than is appropriate') + this.blockRemain -= writeLen + return super.write(data) } -} -const streamSync = (opt, p, position, fd, files) => { - const stream = new fsm.WriteStreamSync(opt.file, { - fd: fd, - start: position - }) - p.pipe(stream) - addFilesSync(p, files) -} + end () { + if (this.blockRemain) + this.write(Buffer.alloc(this.blockRemain)) + return super.end() + } +}) -const replace = (opt, files, cb) => { - files = Array.from(files) - const p = new Pack(opt) +WriteEntry.Sync = WriteEntrySync +WriteEntry.Tar = WriteEntryTar - const getPos = (fd, size, cb_) => { - const cb = (er, pos) => { - if (er) - fs.close(fd, _ => cb_(er)) - else - cb_(null, pos) - } +const getType = stat => + stat.isFile() ? 'File' + : stat.isDirectory() ? 'Directory' + : stat.isSymbolicLink() ? 'SymbolicLink' + : 'Unsupported' - let position = 0 - if (size === 0) - return cb(null, 0) +module.exports = WriteEntry - let bufPos = 0 - const headBuf = Buffer.alloc(512) - const onread = (er, bytes) => { - if (er) - return cb(er) - bufPos += bytes - if (bufPos < 512 && bytes) - return fs.read( - fd, headBuf, bufPos, headBuf.length - bufPos, - position + bufPos, onread - ) - if (position === 0 && headBuf[0] === 0x1f && headBuf[1] === 0x8b) - return cb(new Error('cannot append to compressed archives')) +/***/ }), +/* 294 */ +/***/ (function(module, exports, __webpack_require__) { - // truncated header - if (bufPos < 512) - return cb(null, position) +"use strict"; - const h = new Header(headBuf) - if (!h.cksumValid) - return cb(null, position) +const Buffer = __webpack_require__(282) +const Header = __webpack_require__(295) +const path = __webpack_require__(20) - const entryBlockSize = 512 * Math.ceil(h.size / 512) - if (position + entryBlockSize + 512 > size) - return cb(null, position) +class Pax { + constructor (obj, global) { + this.atime = obj.atime || null + this.charset = obj.charset || null + this.comment = obj.comment || null + this.ctime = obj.ctime || null + this.gid = obj.gid || null + this.gname = obj.gname || null + this.linkpath = obj.linkpath || null + this.mtime = obj.mtime || null + this.path = obj.path || null + this.size = obj.size || null + this.uid = obj.uid || null + this.uname = obj.uname || null + this.dev = obj.dev || null + this.ino = obj.ino || null + this.nlink = obj.nlink || null + this.global = global || false + } - position += entryBlockSize + 512 - if (position >= size) - return cb(null, position) + encode () { + const body = this.encodeBody() + if (body === '') + return null - if (opt.mtimeCache) - opt.mtimeCache.set(h.path, h.mtime) - bufPos = 0 - fs.read(fd, headBuf, 0, 512, position, onread) + const bodyLen = Buffer.byteLength(body) + // round up to 512 bytes + // add 512 for header + const bufLen = 512 * Math.ceil(1 + bodyLen / 512) + const buf = Buffer.allocUnsafe(bufLen) + + // 0-fill the header section, it might not hit every field + for (let i = 0; i < 512; i++) { + buf[i] = 0 } - fs.read(fd, headBuf, 0, 512, position, onread) - } - const promise = new Promise((resolve, reject) => { - p.on('error', reject) - let flag = 'r+' - const onopen = (er, fd) => { - if (er && er.code === 'ENOENT' && flag === 'r+') { - flag = 'w+' - return fs.open(opt.file, flag, onopen) - } + new Header({ + // XXX split the path + // then the path should be PaxHeader + basename, but less than 99, + // prepend with the dirname + path: ('PaxHeader/' + path.basename(this.path)).slice(0, 99), + mode: this.mode || 0o644, + uid: this.uid || null, + gid: this.gid || null, + size: bodyLen, + mtime: this.mtime || null, + type: this.global ? 'GlobalExtendedHeader' : 'ExtendedHeader', + linkpath: '', + uname: this.uname || '', + gname: this.gname || '', + devmaj: 0, + devmin: 0, + atime: this.atime || null, + ctime: this.ctime || null + }).encode(buf) - if (er) - return reject(er) + buf.write(body, 512, bodyLen, 'utf8') - fs.fstat(fd, (er, st) => { - if (er) - return reject(er) - getPos(fd, st.size, (er, position) => { - if (er) - return reject(er) - const stream = new fsm.WriteStream(opt.file, { - fd: fd, - start: position - }) - p.pipe(stream) - stream.on('error', reject) - stream.on('close', resolve) - addFilesAsync(p, files) - }) - }) + // null pad after the body + for (let i = bodyLen + 512; i < buf.length; i++) { + buf[i] = 0 } - fs.open(opt.file, flag, onopen) - }) - return cb ? promise.then(cb, cb) : promise -} + return buf + } -const addFilesSync = (p, files) => { - files.forEach(file => { - if (file.charAt(0) === '@') - t({ - file: path.resolve(p.cwd, file.substr(1)), - sync: true, - noResume: true, - onentry: entry => p.add(entry) - }) - else - p.add(file) - }) - p.end() -} + encodeBody () { + return ( + this.encodeField('path') + + this.encodeField('ctime') + + this.encodeField('atime') + + this.encodeField('dev') + + this.encodeField('ino') + + this.encodeField('nlink') + + this.encodeField('charset') + + this.encodeField('comment') + + this.encodeField('gid') + + this.encodeField('gname') + + this.encodeField('linkpath') + + this.encodeField('mtime') + + this.encodeField('size') + + this.encodeField('uid') + + this.encodeField('uname') + ) + } -const addFilesAsync = (p, files) => { - while (files.length) { - const file = files.shift() - if (file.charAt(0) === '@') - return t({ - file: path.resolve(p.cwd, file.substr(1)), - noResume: true, - onentry: entry => p.add(entry) - }).then(_ => addFilesAsync(p, files)) - else - p.add(file) + encodeField (field) { + if (this[field] === null || this[field] === undefined) + return '' + const v = this[field] instanceof Date ? this[field].getTime() / 1000 + : this[field] + const s = ' ' + + (field === 'dev' || field === 'ino' || field === 'nlink' + ? 'SCHILY.' : '') + + field + '=' + v + '\n' + const byteLen = Buffer.byteLength(s) + // the digits includes the length of the digits in ascii base-10 + // so if it's 9 characters, then adding 1 for the 9 makes it 10 + // which makes it 11 chars. + let digits = Math.floor(Math.log(byteLen) / Math.log(10)) + 1 + if (byteLen + digits >= Math.pow(10, digits)) + digits += 1 + const len = digits + byteLen + return len + s } - p.end() } +Pax.parse = (string, ex, g) => new Pax(merge(parseKV(string), ex), g) -/***/ }), -/* 302 */ -/***/ (function(module, exports, __webpack_require__) { +const merge = (a, b) => + b ? Object.keys(a).reduce((s, k) => (s[k] = a[k], s), b) : a -"use strict"; +const parseKV = string => + string + .replace(/\n$/, '') + .split('\n') + .reduce(parseKVLine, Object.create(null)) +const parseKVLine = (set, line) => { + const n = parseInt(line, 10) -// tar -u + // XXX Values with \n in them will fail this. + // Refactor to not be a naive line-by-line parse. + if (n !== Buffer.byteLength(line) + 1) + return set -const hlo = __webpack_require__(278) -const r = __webpack_require__(301) -// just call tar.r with the filter and mtimeCache + line = line.substr((n + ' ').length) + const kv = line.split('=') + const k = kv.shift().replace(/^SCHILY\.(dev|ino|nlink)/, '$1') + if (!k) + return set -const u = module.exports = (opt_, files, cb) => { - const opt = hlo(opt_) + const v = kv.join('=') + set[k] = /^([A-Z]+\.)?([mac]|birth|creation)time$/.test(k) + ? new Date(v * 1000) + : /^[0-9]+$/.test(v) ? +v + : v + return set +} - if (!opt.file) - throw new TypeError('file is required') +module.exports = Pax - if (opt.gzip) - throw new TypeError('cannot append to compressed archives') - if (!files || !Array.isArray(files) || !files.length) - throw new TypeError('no files or directories specified') +/***/ }), +/* 295 */ +/***/ (function(module, exports, __webpack_require__) { - files = Array.from(files) +"use strict"; - mtimeFilter(opt) - return r(opt, files, cb) -} +// parse a 512-byte header block to a data object, or vice-versa +// encode returns `true` if a pax extended header is needed, because +// the data could not be faithfully encoded in a simple header. +// (Also, check header.needPax to see if it needs a pax header.) -const mtimeFilter = opt => { - const filter = opt.filter +const Buffer = __webpack_require__(282) +const types = __webpack_require__(292) +const pathModule = __webpack_require__(20).posix +const large = __webpack_require__(296) - if (!opt.mtimeCache) - opt.mtimeCache = new Map() +const SLURP = Symbol('slurp') +const TYPE = Symbol('type') - opt.filter = filter ? (path, stat) => - filter(path, stat) && !(opt.mtimeCache.get(path) > stat.mtime) - : (path, stat) => !(opt.mtimeCache.get(path) > stat.mtime) -} +class Header { + constructor (data, off, ex, gex) { + this.cksumValid = false + this.needPax = false + this.nullBlock = false + this.block = null + this.path = null + this.mode = null + this.uid = null + this.gid = null + this.size = null + this.mtime = null + this.cksum = null + this[TYPE] = '0' + this.linkpath = null + this.uname = null + this.gname = null + this.devmaj = 0 + this.devmin = 0 + this.atime = null + this.ctime = null -/***/ }), -/* 303 */ -/***/ (function(module, exports, __webpack_require__) { + if (Buffer.isBuffer(data)) + this.decode(data, off || 0, ex, gex) + else if (data) + this.set(data) + } -"use strict"; + decode (buf, off, ex, gex) { + if (!off) + off = 0 + if (!buf || !(buf.length >= off + 512)) + throw new Error('need 512 bytes for header') -// tar -x -const hlo = __webpack_require__(278) -const Unpack = __webpack_require__(304) -const fs = __webpack_require__(4) -const fsm = __webpack_require__(298) -const path = __webpack_require__(20) + this.path = decString(buf, off, 100) + this.mode = decNumber(buf, off + 100, 8) + this.uid = decNumber(buf, off + 108, 8) + this.gid = decNumber(buf, off + 116, 8) + this.size = decNumber(buf, off + 124, 12) + this.mtime = decDate(buf, off + 136, 12) + this.cksum = decNumber(buf, off + 148, 12) -const x = module.exports = (opt_, files, cb) => { - if (typeof opt_ === 'function') - cb = opt_, files = null, opt_ = {} - else if (Array.isArray(opt_)) - files = opt_, opt_ = {} + // if we have extended or global extended headers, apply them now + // See https://github.com/npm/node-tar/pull/187 + this[SLURP](ex) + this[SLURP](gex, true) - if (typeof files === 'function') - cb = files, files = null + // old tar versions marked dirs as a file with a trailing / + this[TYPE] = decString(buf, off + 156, 1) + if (this[TYPE] === '') + this[TYPE] = '0' + if (this[TYPE] === '0' && this.path.substr(-1) === '/') + this[TYPE] = '5' - if (!files) - files = [] - else - files = Array.from(files) + // tar implementations sometimes incorrectly put the stat(dir).size + // as the size in the tarball, even though Directory entries are + // not able to have any body at all. In the very rare chance that + // it actually DOES have a body, we weren't going to do anything with + // it anyway, and it'll just be a warning about an invalid header. + if (this[TYPE] === '5') + this.size = 0 - const opt = hlo(opt_) + this.linkpath = decString(buf, off + 157, 100) + if (buf.slice(off + 257, off + 265).toString() === 'ustar\u000000') { + this.uname = decString(buf, off + 265, 32) + this.gname = decString(buf, off + 297, 32) + this.devmaj = decNumber(buf, off + 329, 8) + this.devmin = decNumber(buf, off + 337, 8) + if (buf[off + 475] !== 0) { + // definitely a prefix, definitely >130 chars. + const prefix = decString(buf, off + 345, 155) + this.path = prefix + '/' + this.path + } else { + const prefix = decString(buf, off + 345, 130) + if (prefix) + this.path = prefix + '/' + this.path + this.atime = decDate(buf, off + 476, 12) + this.ctime = decDate(buf, off + 488, 12) + } + } - if (opt.sync && typeof cb === 'function') - throw new TypeError('callback not supported for sync tar functions') + let sum = 8 * 0x20 + for (let i = off; i < off + 148; i++) { + sum += buf[i] + } + for (let i = off + 156; i < off + 512; i++) { + sum += buf[i] + } + this.cksumValid = sum === this.cksum + if (this.cksum === null && sum === 8 * 0x20) + this.nullBlock = true + } - if (!opt.file && typeof cb === 'function') - throw new TypeError('callback only supported with file option') + [SLURP] (ex, global) { + for (let k in ex) { + // we slurp in everything except for the path attribute in + // a global extended header, because that's weird. + if (ex[k] !== null && ex[k] !== undefined && + !(global && k === 'path')) + this[k] = ex[k] + } + } - if (files.length) - filesFilter(opt, files) + encode (buf, off) { + if (!buf) { + buf = this.block = Buffer.alloc(512) + off = 0 + } - return opt.file && opt.sync ? extractFileSync(opt) - : opt.file ? extractFile(opt, cb) - : opt.sync ? extractSync(opt) - : extract(opt) -} + if (!off) + off = 0 -// construct a filter that limits the file entries listed -// include child entries if a dir is included -const filesFilter = (opt, files) => { - const map = new Map(files.map(f => [f.replace(/\/+$/, ''), true])) - const filter = opt.filter + if (!(buf.length >= off + 512)) + throw new Error('need 512 bytes for header') - const mapHas = (file, r) => { - const root = r || path.parse(file).root || '.' - const ret = file === root ? false - : map.has(file) ? map.get(file) - : mapHas(path.dirname(file), root) + const prefixSize = this.ctime || this.atime ? 130 : 155 + const split = splitPrefix(this.path || '', prefixSize) + const path = split[0] + const prefix = split[1] + this.needPax = split[2] - map.set(file, ret) - return ret + this.needPax = encString(buf, off, 100, path) || this.needPax + this.needPax = encNumber(buf, off + 100, 8, this.mode) || this.needPax + this.needPax = encNumber(buf, off + 108, 8, this.uid) || this.needPax + this.needPax = encNumber(buf, off + 116, 8, this.gid) || this.needPax + this.needPax = encNumber(buf, off + 124, 12, this.size) || this.needPax + this.needPax = encDate(buf, off + 136, 12, this.mtime) || this.needPax + buf[off + 156] = this[TYPE].charCodeAt(0) + this.needPax = encString(buf, off + 157, 100, this.linkpath) || this.needPax + buf.write('ustar\u000000', off + 257, 8) + this.needPax = encString(buf, off + 265, 32, this.uname) || this.needPax + this.needPax = encString(buf, off + 297, 32, this.gname) || this.needPax + this.needPax = encNumber(buf, off + 329, 8, this.devmaj) || this.needPax + this.needPax = encNumber(buf, off + 337, 8, this.devmin) || this.needPax + this.needPax = encString(buf, off + 345, prefixSize, prefix) || this.needPax + if (buf[off + 475] !== 0) + this.needPax = encString(buf, off + 345, 155, prefix) || this.needPax + else { + this.needPax = encString(buf, off + 345, 130, prefix) || this.needPax + this.needPax = encDate(buf, off + 476, 12, this.atime) || this.needPax + this.needPax = encDate(buf, off + 488, 12, this.ctime) || this.needPax + } + + let sum = 8 * 0x20 + for (let i = off; i < off + 148; i++) { + sum += buf[i] + } + for (let i = off + 156; i < off + 512; i++) { + sum += buf[i] + } + this.cksum = sum + encNumber(buf, off + 148, 8, this.cksum) + this.cksumValid = true + + return this.needPax } - opt.filter = filter - ? (file, entry) => filter(file, entry) && mapHas(file.replace(/\/+$/, '')) - : file => mapHas(file.replace(/\/+$/, '')) -} + set (data) { + for (let i in data) { + if (data[i] !== null && data[i] !== undefined) + this[i] = data[i] + } + } -const extractFileSync = opt => { - const u = new Unpack.Sync(opt) + get type () { + return types.name.get(this[TYPE]) || this[TYPE] + } - const file = opt.file - let threw = true - let fd - const stat = fs.statSync(file) - // This trades a zero-byte read() syscall for a stat - // However, it will usually result in less memory allocation - const readSize = opt.maxReadSize || 16*1024*1024 - const stream = new fsm.ReadStreamSync(file, { - readSize: readSize, - size: stat.size - }) - stream.pipe(u) + get typeKey () { + return this[TYPE] + } + + set type (type) { + if (types.code.has(type)) + this[TYPE] = types.code.get(type) + else + this[TYPE] = type + } } -const extractFile = (opt, cb) => { - const u = new Unpack(opt) - const readSize = opt.maxReadSize || 16*1024*1024 +const splitPrefix = (p, prefixSize) => { + const pathSize = 100 + let pp = p + let prefix = '' + let ret + const root = pathModule.parse(p).root || '.' - const file = opt.file - const p = new Promise((resolve, reject) => { - u.on('error', reject) - u.on('close', resolve) + if (Buffer.byteLength(pp) < pathSize) + ret = [pp, prefix, false] + else { + // first set prefix to the dir, and path to the base + prefix = pathModule.dirname(pp) + pp = pathModule.basename(pp) + + do { + // both fit! + if (Buffer.byteLength(pp) <= pathSize && + Buffer.byteLength(prefix) <= prefixSize) + ret = [pp, prefix, false] + + // prefix fits in prefix, but path doesn't fit in path + else if (Buffer.byteLength(pp) > pathSize && + Buffer.byteLength(prefix) <= prefixSize) + ret = [pp.substr(0, pathSize - 1), prefix, true] - // This trades a zero-byte read() syscall for a stat - // However, it will usually result in less memory allocation - fs.stat(file, (er, stat) => { - if (er) - reject(er) else { - const stream = new fsm.ReadStream(file, { - readSize: readSize, - size: stat.size - }) - stream.on('error', reject) - stream.pipe(u) + // make path take a bit from prefix + pp = pathModule.join(pathModule.basename(prefix), pp) + prefix = pathModule.dirname(prefix) } - }) - }) - return cb ? p.then(cb, cb) : p -} + } while (prefix !== root && !ret) -const extractSync = opt => { - return new Unpack.Sync(opt) + // at this point, found no resolution, just truncate + if (!ret) + ret = [p.substr(0, pathSize - 1), '', true] + } + return ret } -const extract = opt => { - return new Unpack(opt) -} +const decString = (buf, off, size) => + buf.slice(off, off + size).toString('utf8').replace(/\0.*/, '') +const decDate = (buf, off, size) => + numToDate(decNumber(buf, off, size)) -/***/ }), -/* 304 */ -/***/ (function(module, exports, __webpack_require__) { +const numToDate = num => num === null ? null : new Date(num * 1000) -"use strict"; +const decNumber = (buf, off, size) => + buf[off] & 0x80 ? large.parse(buf.slice(off, off + size)) + : decSmallNumber(buf, off, size) +const nanNull = value => isNaN(value) ? null : value -const assert = __webpack_require__(46) -const EE = __webpack_require__(137).EventEmitter -const Parser = __webpack_require__(300) -const fs = __webpack_require__(4) -const fsm = __webpack_require__(298) -const path = __webpack_require__(20) -const mkdir = __webpack_require__(305) -const mkdirSync = mkdir.sync -const wc = __webpack_require__(296) +const decSmallNumber = (buf, off, size) => + nanNull(parseInt( + buf.slice(off, off + size) + .toString('utf8').replace(/\0.*$/, '').trim(), 8)) -const ONENTRY = Symbol('onEntry') -const CHECKFS = Symbol('checkFs') -const ISREUSABLE = Symbol('isReusable') -const MAKEFS = Symbol('makeFs') -const FILE = Symbol('file') -const DIRECTORY = Symbol('directory') -const LINK = Symbol('link') -const SYMLINK = Symbol('symlink') -const HARDLINK = Symbol('hardlink') -const UNSUPPORTED = Symbol('unsupported') -const UNKNOWN = Symbol('unknown') -const CHECKPATH = Symbol('checkPath') -const MKDIR = Symbol('mkdir') -const ONERROR = Symbol('onError') -const PENDING = Symbol('pending') -const PEND = Symbol('pend') -const UNPEND = Symbol('unpend') -const ENDED = Symbol('ended') -const MAYBECLOSE = Symbol('maybeClose') -const SKIP = Symbol('skip') -const DOCHOWN = Symbol('doChown') -const UID = Symbol('uid') -const GID = Symbol('gid') -const crypto = __webpack_require__(160) - -// Unlinks on Windows are not atomic. -// -// This means that if you have a file entry, followed by another -// file entry with an identical name, and you cannot re-use the file -// (because it's a hardlink, or because unlink:true is set, or it's -// Windows, which does not have useful nlink values), then the unlink -// will be committed to the disk AFTER the new file has been written -// over the old one, deleting the new file. -// -// To work around this, on Windows systems, we rename the file and then -// delete the renamed file. It's a sloppy kludge, but frankly, I do not -// know of a better way to do this, given windows' non-atomic unlink -// semantics. -// -// See: https://github.com/npm/node-tar/issues/183 -/* istanbul ignore next */ -const unlinkFile = (path, cb) => { - if (process.platform !== 'win32') - return fs.unlink(path, cb) - - const name = path + '.DELETE.' + crypto.randomBytes(16).toString('hex') - fs.rename(path, name, er => { - if (er) - return cb(er) - fs.unlink(name, cb) - }) -} - -/* istanbul ignore next */ -const unlinkFileSync = path => { - if (process.platform !== 'win32') - return fs.unlinkSync(path) - - const name = path + '.DELETE.' + crypto.randomBytes(16).toString('hex') - fs.renameSync(path, name) - fs.unlinkSync(name) +// the maximum encodable as a null-terminated octal, by field size +const MAXNUM = { + 12: 0o77777777777, + 8 : 0o7777777 } -// this.gid, entry.gid, this.processUid -const uint32 = (a, b, c) => - a === a >>> 0 ? a - : b === b >>> 0 ? b - : c - -class Unpack extends Parser { - constructor (opt) { - if (!opt) - opt = {} - - opt.ondone = _ => { - this[ENDED] = true - this[MAYBECLOSE]() - } - - super(opt) - - this.transform = typeof opt.transform === 'function' ? opt.transform : null - - this.writable = true - this.readable = false +const encNumber = (buf, off, size, number) => + number === null ? false : + number > MAXNUM[size] || number < 0 + ? (large.encode(number, buf.slice(off, off + size)), true) + : (encSmallNumber(buf, off, size, number), false) - this[PENDING] = 0 - this[ENDED] = false +const encSmallNumber = (buf, off, size, number) => + buf.write(octalString(number, size), off, size, 'ascii') - this.dirCache = opt.dirCache || new Map() +const octalString = (number, size) => + padOctal(Math.floor(number).toString(8), size) - if (typeof opt.uid === 'number' || typeof opt.gid === 'number') { - // need both or neither - if (typeof opt.uid !== 'number' || typeof opt.gid !== 'number') - throw new TypeError('cannot set owner without number uid and gid') - if (opt.preserveOwner) - throw new TypeError( - 'cannot preserve owner in archive and also set owner explicitly') - this.uid = opt.uid - this.gid = opt.gid - this.setOwner = true - } else { - this.uid = null - this.gid = null - this.setOwner = false - } +const padOctal = (string, size) => + (string.length === size - 1 ? string + : new Array(size - string.length - 1).join('0') + string + ' ') + '\0' - // default true for root - if (opt.preserveOwner === undefined && typeof opt.uid !== 'number') - this.preserveOwner = process.getuid && process.getuid() === 0 - else - this.preserveOwner = !!opt.preserveOwner +const encDate = (buf, off, size, date) => + date === null ? false : + encNumber(buf, off, size, date.getTime() / 1000) - this.processUid = (this.preserveOwner || this.setOwner) && process.getuid ? - process.getuid() : null - this.processGid = (this.preserveOwner || this.setOwner) && process.getgid ? - process.getgid() : null +// enough to fill the longest string we've got +const NULLS = new Array(156).join('\0') +// pad with nulls, return true if it's longer or non-ascii +const encString = (buf, off, size, string) => + string === null ? false : + (buf.write(string + NULLS, off, size, 'utf8'), + string.length !== Buffer.byteLength(string) || string.length > size) - // mostly just for testing, but useful in some cases. - // Forcibly trigger a chown on every entry, no matter what - this.forceChown = opt.forceChown === true +module.exports = Header - // turn > { + if (!Number.isSafeInteger(num)) + // The number is so large that javascript cannot represent it with integer + // precision. + throw TypeError('cannot encode number outside of javascript safe integer range') + else if (num < 0) + encodeNegative(num, buf) + else + encodePositive(num, buf) + return buf +} - // unlink files and links before writing. This breaks existing hard - // links, and removes symlink directories rather than erroring - this.unlink = !!opt.unlink +const encodePositive = (num, buf) => { + buf[0] = 0x80 - this.cwd = path.resolve(opt.cwd || process.cwd()) - this.strip = +opt.strip || 0 - this.processUmask = process.umask() - this.umask = typeof opt.umask === 'number' ? opt.umask : this.processUmask - // default mode for dirs created as parents - this.dmode = opt.dmode || (0o0777 & (~this.umask)) - this.fmode = opt.fmode || (0o0666 & (~this.umask)) - this.on('entry', entry => this[ONENTRY](entry)) + for (var i = buf.length; i > 1; i--) { + buf[i-1] = num & 0xff + num = Math.floor(num / 0x100) } +} - [MAYBECLOSE] () { - if (this[ENDED] && this[PENDING] === 0) { - this.emit('prefinish') - this.emit('finish') - this.emit('end') - this.emit('close') +const encodeNegative = (num, buf) => { + buf[0] = 0xff + var flipped = false + num = num * -1 + for (var i = buf.length; i > 1; i--) { + var byte = num & 0xff + num = Math.floor(num / 0x100) + if (flipped) + buf[i-1] = onesComp(byte) + else if (byte === 0) + buf[i-1] = 0 + else { + flipped = true + buf[i-1] = twosComp(byte) } } +} - [CHECKPATH] (entry) { - if (this.strip) { - const parts = entry.path.split(/\/|\\/) - if (parts.length < this.strip) - return false - entry.path = parts.slice(this.strip).join('/') - - if (entry.type === 'Link') { - const linkparts = entry.linkpath.split(/\/|\\/) - if (linkparts.length >= this.strip) - entry.linkpath = linkparts.slice(this.strip).join('/') - } - } +const parse = exports.parse = (buf) => { + var post = buf[buf.length - 1] + var pre = buf[0] + var value; + if (pre === 0x80) + value = pos(buf.slice(1, buf.length)) + else if (pre === 0xff) + value = twos(buf) + else + throw TypeError('invalid base256 encoding') - if (!this.preservePaths) { - const p = entry.path - if (p.match(/(^|\/|\\)\.\.(\\|\/|$)/)) { - this.warn('path contains \'..\'', p) - return false - } + if (!Number.isSafeInteger(value)) + // The number is so large that javascript cannot represent it with integer + // precision. + throw TypeError('parsed number outside of javascript safe integer range') - // absolutes on posix are also absolutes on win32 - // so we only need to test this one to get both - if (path.win32.isAbsolute(p)) { - const parsed = path.win32.parse(p) - this.warn('stripping ' + parsed.root + ' from absolute path', p) - entry.path = p.substr(parsed.root.length) - } - } + return value +} - // only encode : chars that aren't drive letter indicators - if (this.win32) { - const parsed = path.win32.parse(entry.path) - entry.path = parsed.root === '' ? wc.encode(entry.path) - : parsed.root + wc.encode(entry.path.substr(parsed.root.length)) +const twos = (buf) => { + var len = buf.length + var sum = 0 + var flipped = false + for (var i = len - 1; i > -1; i--) { + var byte = buf[i] + var f + if (flipped) + f = onesComp(byte) + else if (byte === 0) + f = byte + else { + flipped = true + f = twosComp(byte) } + if (f !== 0) + sum -= f * Math.pow(256, len - i - 1) + } + return sum +} - if (path.isAbsolute(entry.path)) - entry.absolute = entry.path - else - entry.absolute = path.resolve(this.cwd, entry.path) - - return true +const pos = (buf) => { + var len = buf.length + var sum = 0 + for (var i = len - 1; i > -1; i--) { + var byte = buf[i] + if (byte !== 0) + sum += byte * Math.pow(256, len - i - 1) } + return sum +} - [ONENTRY] (entry) { - if (!this[CHECKPATH](entry)) - return entry.resume() +const onesComp = byte => (0xff ^ byte) & 0xff - assert.equal(typeof entry.absolute, 'string') +const twosComp = byte => ((0xff ^ byte) + 1) & 0xff - switch (entry.type) { - case 'Directory': - case 'GNUDumpDir': - if (entry.mode) - entry.mode = entry.mode | 0o700 - case 'File': - case 'OldFile': - case 'ContiguousFile': - case 'Link': - case 'SymbolicLink': - return this[CHECKFS](entry) +/***/ }), +/* 297 */ +/***/ (function(module, exports, __webpack_require__) { - case 'CharacterDevice': - case 'BlockDevice': - case 'FIFO': - return this[UNSUPPORTED](entry) - } - } +"use strict"; - [ONERROR] (er, entry) { - // Cwd has to exist, or else nothing works. That's serious. - // Other errors are warnings, which raise the error in strict - // mode, but otherwise continue on. - if (er.name === 'CwdError') - this.emit('error', er) +module.exports = Base => class extends Base { + warn (msg, data) { + if (!this.strict) + this.emit('warn', msg, data) + else if (data instanceof Error) + this.emit('error', data) else { - this.warn(er.message, er) - this[UNPEND]() - entry.resume() + const er = new Error(msg) + er.data = data + this.emit('error', er) } } +} - [MKDIR] (dir, mode, cb) { - mkdir(dir, { - uid: this.uid, - gid: this.gid, - processUid: this.processUid, - processGid: this.processGid, - umask: this.processUmask, - preserve: this.preservePaths, - unlink: this.unlink, - cache: this.dirCache, - cwd: this.cwd, - mode: mode - }, cb) - } - [DOCHOWN] (entry) { - // in preserve owner mode, chown if the entry doesn't match process - // in set owner mode, chown if setting doesn't match process - return this.forceChown || - this.preserveOwner && - ( typeof entry.uid === 'number' && entry.uid !== this.processUid || - typeof entry.gid === 'number' && entry.gid !== this.processGid ) - || - ( typeof this.uid === 'number' && this.uid !== this.processUid || - typeof this.gid === 'number' && this.gid !== this.processGid ) - } +/***/ }), +/* 298 */ +/***/ (function(module, exports, __webpack_require__) { - [UID] (entry) { - return uint32(this.uid, entry.uid, this.processUid) - } +"use strict"; - [GID] (entry) { - return uint32(this.gid, entry.gid, this.processGid) - } - [FILE] (entry) { - const mode = entry.mode & 0o7777 || this.fmode - const stream = new fsm.WriteStream(entry.absolute, { - mode: mode, - autoClose: false - }) - stream.on('error', er => this[ONERROR](er, entry)) +// When writing files on Windows, translate the characters to their +// 0xf000 higher-encoded versions. - let actions = 1 - const done = er => { - if (er) - return this[ONERROR](er, entry) +const raw = [ + '|', + '<', + '>', + '?', + ':' +] - if (--actions === 0) - fs.close(stream.fd, _ => this[UNPEND]()) - } +const win = raw.map(char => + String.fromCharCode(0xf000 + char.charCodeAt(0))) - stream.on('finish', _ => { - // if futimes fails, try utimes - // if utimes fails, fail with the original error - // same for fchown/chown - const abs = entry.absolute - const fd = stream.fd +const toWin = new Map(raw.map((char, i) => [char, win[i]])) +const toRaw = new Map(win.map((char, i) => [char, raw[i]])) - if (entry.mtime && !this.noMtime) { - actions++ - const atime = entry.atime || new Date() - const mtime = entry.mtime - fs.futimes(fd, atime, mtime, er => - er ? fs.utimes(abs, atime, mtime, er2 => done(er2 && er)) - : done()) - } +module.exports = { + encode: s => raw.reduce((s, c) => s.split(c).join(toWin.get(c)), s), + decode: s => win.reduce((s, c) => s.split(c).join(toRaw.get(c)), s) +} - if (this[DOCHOWN](entry)) { - actions++ - const uid = this[UID](entry) - const gid = this[GID](entry) - fs.fchown(fd, uid, gid, er => - er ? fs.chown(abs, uid, gid, er2 => done(er2 && er)) - : done()) - } - done() - }) +/***/ }), +/* 299 */ +/***/ (function(module, exports, __webpack_require__) { - const tx = this.transform ? this.transform(entry) || entry : entry - if (tx !== entry) { - tx.on('error', er => this[ONERROR](er, entry)) - entry.pipe(tx) - } - tx.pipe(stream) +"use strict"; + +module.exports = (mode, isDir) => { + mode &= 0o7777 + // if dirs are readable, then they should be listable + if (isDir) { + if (mode & 0o400) + mode |= 0o100 + if (mode & 0o40) + mode |= 0o10 + if (mode & 0o4) + mode |= 0o1 } + return mode +} - [DIRECTORY] (entry) { - const mode = entry.mode & 0o7777 || this.dmode - this[MKDIR](entry.absolute, mode, er => { - if (er) - return this[ONERROR](er, entry) - let actions = 1 - const done = _ => { - if (--actions === 0) { - this[UNPEND]() - entry.resume() - } - } +/***/ }), +/* 300 */ +/***/ (function(module, exports, __webpack_require__) { - if (entry.mtime && !this.noMtime) { - actions++ - fs.utimes(entry.absolute, entry.atime || new Date(), entry.mtime, done) - } +"use strict"; - if (this[DOCHOWN](entry)) { - actions++ - fs.chown(entry.absolute, this[UID](entry), this[GID](entry), done) - } +const MiniPass = __webpack_require__(285) +const EE = __webpack_require__(137).EventEmitter +const fs = __webpack_require__(4) - done() - }) - } +// for writev +const binding = process.binding('fs') +const writeBuffers = binding.writeBuffers +const FSReqWrap = binding.FSReqWrap || binding.FSReqCallback - [UNSUPPORTED] (entry) { - this.warn('unsupported entry type: ' + entry.type, entry) - entry.resume() - } +const _autoClose = Symbol('_autoClose') +const _close = Symbol('_close') +const _ended = Symbol('_ended') +const _fd = Symbol('_fd') +const _finished = Symbol('_finished') +const _flags = Symbol('_flags') +const _flush = Symbol('_flush') +const _handleChunk = Symbol('_handleChunk') +const _makeBuf = Symbol('_makeBuf') +const _mode = Symbol('_mode') +const _needDrain = Symbol('_needDrain') +const _onerror = Symbol('_onerror') +const _onopen = Symbol('_onopen') +const _onread = Symbol('_onread') +const _onwrite = Symbol('_onwrite') +const _open = Symbol('_open') +const _path = Symbol('_path') +const _pos = Symbol('_pos') +const _queue = Symbol('_queue') +const _read = Symbol('_read') +const _readSize = Symbol('_readSize') +const _reading = Symbol('_reading') +const _remain = Symbol('_remain') +const _size = Symbol('_size') +const _write = Symbol('_write') +const _writing = Symbol('_writing') +const _defaultFlag = Symbol('_defaultFlag') - [SYMLINK] (entry) { - this[LINK](entry, entry.linkpath, 'symlink') - } +class ReadStream extends MiniPass { + constructor (path, opt) { + opt = opt || {} + super(opt) - [HARDLINK] (entry) { - this[LINK](entry, path.resolve(this.cwd, entry.linkpath), 'link') - } + this.writable = false - [PEND] () { - this[PENDING]++ - } + if (typeof path !== 'string') + throw new TypeError('path must be a string') - [UNPEND] () { - this[PENDING]-- - this[MAYBECLOSE]() + this[_fd] = typeof opt.fd === 'number' ? opt.fd : null + this[_path] = path + this[_readSize] = opt.readSize || 16*1024*1024 + this[_reading] = false + this[_size] = typeof opt.size === 'number' ? opt.size : Infinity + this[_remain] = this[_size] + this[_autoClose] = typeof opt.autoClose === 'boolean' ? + opt.autoClose : true + + if (typeof this[_fd] === 'number') + this[_read]() + else + this[_open]() } - [SKIP] (entry) { - this[UNPEND]() - entry.resume() + get fd () { return this[_fd] } + get path () { return this[_path] } + + write () { + throw new TypeError('this is a readable stream') } - // Check if we can reuse an existing filesystem entry safely and - // overwrite it, rather than unlinking and recreating - // Windows doesn't report a useful nlink, so we just never reuse entries - [ISREUSABLE] (entry, st) { - return entry.type === 'File' && - !this.unlink && - st.isFile() && - st.nlink <= 1 && - process.platform !== 'win32' + end () { + throw new TypeError('this is a readable stream') } - // check if a thing is there, and if so, try to clobber it - [CHECKFS] (entry) { - this[PEND]() - this[MKDIR](path.dirname(entry.absolute), this.dmode, er => { - if (er) - return this[ONERROR](er, entry) - fs.lstat(entry.absolute, (er, st) => { - if (st && (this.keep || this.newer && st.mtime > entry.mtime)) - this[SKIP](entry) - else if (er || this[ISREUSABLE](entry, st)) - this[MAKEFS](null, entry) - else if (st.isDirectory()) { - if (entry.type === 'Directory') { - if (!entry.mode || (st.mode & 0o7777) === entry.mode) - this[MAKEFS](null, entry) - else - fs.chmod(entry.absolute, entry.mode, er => this[MAKEFS](er, entry)) - } else - fs.rmdir(entry.absolute, er => this[MAKEFS](er, entry)) - } else - unlinkFile(entry.absolute, er => this[MAKEFS](er, entry)) - }) - }) + [_open] () { + fs.open(this[_path], 'r', (er, fd) => this[_onopen](er, fd)) } - [MAKEFS] (er, entry) { + [_onopen] (er, fd) { if (er) - return this[ONERROR](er, entry) + this[_onerror](er) + else { + this[_fd] = fd + this.emit('open', fd) + this[_read]() + } + } - switch (entry.type) { - case 'File': - case 'OldFile': - case 'ContiguousFile': - return this[FILE](entry) + [_makeBuf] () { + return Buffer.allocUnsafe(Math.min(this[_readSize], this[_remain])) + } - case 'Link': - return this[HARDLINK](entry) + [_read] () { + if (!this[_reading]) { + this[_reading] = true + const buf = this[_makeBuf]() + /* istanbul ignore if */ + if (buf.length === 0) return process.nextTick(() => this[_onread](null, 0, buf)) + fs.read(this[_fd], buf, 0, buf.length, null, (er, br, buf) => + this[_onread](er, br, buf)) + } + } - case 'SymbolicLink': - return this[SYMLINK](entry) + [_onread] (er, br, buf) { + this[_reading] = false + if (er) + this[_onerror](er) + else if (this[_handleChunk](br, buf)) + this[_read]() + } - case 'Directory': - case 'GNUDumpDir': - return this[DIRECTORY](entry) + [_close] () { + if (this[_autoClose] && typeof this[_fd] === 'number') { + fs.close(this[_fd], _ => this.emit('close')) + this[_fd] = null } } - [LINK] (entry, linkpath, link) { - // XXX: get the type ('file' or 'dir') for windows - fs[link](linkpath, entry.absolute, er => { - if (er) - return this[ONERROR](er, entry) - this[UNPEND]() - entry.resume() - }) + [_onerror] (er) { + this[_reading] = true + this[_close]() + this.emit('error', er) + } + + [_handleChunk] (br, buf) { + let ret = false + // no effect if infinite + this[_remain] -= br + if (br > 0) + ret = super.write(br < buf.length ? buf.slice(0, br) : buf) + + if (br === 0 || this[_remain] <= 0) { + ret = false + this[_close]() + super.end() + } + + return ret + } + + emit (ev, data) { + switch (ev) { + case 'prefinish': + case 'finish': + break + + case 'drain': + if (typeof this[_fd] === 'number') + this[_read]() + break + + default: + return super.emit(ev, data) + } } } -class UnpackSync extends Unpack { - constructor (opt) { - super(opt) +class ReadStreamSync extends ReadStream { + [_open] () { + let threw = true + try { + this[_onopen](null, fs.openSync(this[_path], 'r')) + threw = false + } finally { + if (threw) + this[_close]() + } } - [CHECKFS] (entry) { - const er = this[MKDIR](path.dirname(entry.absolute), this.dmode) - if (er) - return this[ONERROR](er, entry) + [_read] () { + let threw = true try { - const st = fs.lstatSync(entry.absolute) - if (this.keep || this.newer && st.mtime > entry.mtime) - return this[SKIP](entry) - else if (this[ISREUSABLE](entry, st)) - return this[MAKEFS](null, entry) - else { - try { - if (st.isDirectory()) { - if (entry.type === 'Directory') { - if (entry.mode && (st.mode & 0o7777) !== entry.mode) - fs.chmodSync(entry.absolute, entry.mode) - } else - fs.rmdirSync(entry.absolute) - } else - unlinkFileSync(entry.absolute) - return this[MAKEFS](null, entry) - } catch (er) { - return this[ONERROR](er, entry) - } + if (!this[_reading]) { + this[_reading] = true + do { + const buf = this[_makeBuf]() + /* istanbul ignore next */ + const br = buf.length === 0 ? 0 : fs.readSync(this[_fd], buf, 0, buf.length, null) + if (!this[_handleChunk](br, buf)) + break + } while (true) + this[_reading] = false } - } catch (er) { - return this[MAKEFS](null, entry) + threw = false + } finally { + if (threw) + this[_close]() } } - [FILE] (entry) { - const mode = entry.mode & 0o7777 || this.fmode + [_close] () { + if (this[_autoClose] && typeof this[_fd] === 'number') { + try { + fs.closeSync(this[_fd]) + } catch (er) {} + this[_fd] = null + this.emit('close') + } + } +} - const oner = er => { - try { fs.closeSync(fd) } catch (_) {} - if (er) - this[ONERROR](er, entry) +class WriteStream extends EE { + constructor (path, opt) { + opt = opt || {} + super(opt) + this.readable = false + this[_writing] = false + this[_ended] = false + this[_needDrain] = false + this[_queue] = [] + this[_path] = path + this[_fd] = typeof opt.fd === 'number' ? opt.fd : null + this[_mode] = opt.mode === undefined ? 0o666 : opt.mode + this[_pos] = typeof opt.start === 'number' ? opt.start : null + this[_autoClose] = typeof opt.autoClose === 'boolean' ? + opt.autoClose : true + + // truncating makes no sense when writing into the middle + const defaultFlag = this[_pos] !== null ? 'r+' : 'w' + this[_defaultFlag] = opt.flags === undefined + this[_flags] = this[_defaultFlag] ? defaultFlag : opt.flags + + if (this[_fd] === null) + this[_open]() + } + + get fd () { return this[_fd] } + get path () { return this[_path] } + + [_onerror] (er) { + this[_close]() + this[_writing] = true + this.emit('error', er) + } + + [_open] () { + fs.open(this[_path], this[_flags], this[_mode], + (er, fd) => this[_onopen](er, fd)) + } + + [_onopen] (er, fd) { + if (this[_defaultFlag] && + this[_flags] === 'r+' && + er && er.code === 'ENOENT') { + this[_flags] = 'w' + this[_open]() + } else if (er) + this[_onerror](er) + else { + this[_fd] = fd + this.emit('open', fd) + this[_flush]() } + } - let stream - let fd - try { - fd = fs.openSync(entry.absolute, 'w', mode) - } catch (er) { - return oner(er) + end (buf, enc) { + if (buf) + this.write(buf, enc) + + this[_ended] = true + + // synthetic after-write logic, where drain/finish live + if (!this[_writing] && !this[_queue].length && + typeof this[_fd] === 'number') + this[_onwrite](null, 0) + } + + write (buf, enc) { + if (typeof buf === 'string') + buf = new Buffer(buf, enc) + + if (this[_ended]) { + this.emit('error', new Error('write() after end()')) + return false } - const tx = this.transform ? this.transform(entry) || entry : entry - if (tx !== entry) { - tx.on('error', er => this[ONERROR](er, entry)) - entry.pipe(tx) + + if (this[_fd] === null || this[_writing] || this[_queue].length) { + this[_queue].push(buf) + this[_needDrain] = true + return false } - tx.on('data', chunk => { - try { - fs.writeSync(fd, chunk, 0, chunk.length) - } catch (er) { - oner(er) - } - }) + this[_writing] = true + this[_write](buf) + return true + } - tx.on('end', _ => { - let er = null - // try both, falling futimes back to utimes - // if either fails, handle the first error - if (entry.mtime && !this.noMtime) { - const atime = entry.atime || new Date() - const mtime = entry.mtime - try { - fs.futimesSync(fd, atime, mtime) - } catch (futimeser) { - try { - fs.utimesSync(entry.absolute, atime, mtime) - } catch (utimeser) { - er = futimeser - } - } - } + [_write] (buf) { + fs.write(this[_fd], buf, 0, buf.length, this[_pos], (er, bw) => + this[_onwrite](er, bw)) + } - if (this[DOCHOWN](entry)) { - const uid = this[UID](entry) - const gid = this[GID](entry) + [_onwrite] (er, bw) { + if (er) + this[_onerror](er) + else { + if (this[_pos] !== null) + this[_pos] += bw + if (this[_queue].length) + this[_flush]() + else { + this[_writing] = false - try { - fs.fchownSync(fd, uid, gid) - } catch (fchowner) { - try { - fs.chownSync(entry.absolute, uid, gid) - } catch (chowner) { - er = er || fchowner - } + if (this[_ended] && !this[_finished]) { + this[_finished] = true + this[_close]() + this.emit('finish') + } else if (this[_needDrain]) { + this[_needDrain] = false + this.emit('drain') } } - - oner(er) - }) + } } - [DIRECTORY] (entry) { - const mode = entry.mode & 0o7777 || this.dmode - const er = this[MKDIR](entry.absolute, mode) - if (er) - return this[ONERROR](er, entry) - if (entry.mtime && !this.noMtime) { - try { - fs.utimesSync(entry.absolute, entry.atime || new Date(), entry.mtime) - } catch (er) {} + [_flush] () { + if (this[_queue].length === 0) { + if (this[_ended]) + this[_onwrite](null, 0) + } else if (this[_queue].length === 1) + this[_write](this[_queue].pop()) + else { + const iovec = this[_queue] + this[_queue] = [] + writev(this[_fd], iovec, this[_pos], + (er, bw) => this[_onwrite](er, bw)) } - if (this[DOCHOWN](entry)) { - try { - fs.chownSync(entry.absolute, this[UID](entry), this[GID](entry)) - } catch (er) {} + } + + [_close] () { + if (this[_autoClose] && typeof this[_fd] === 'number') { + fs.close(this[_fd], _ => this.emit('close')) + this[_fd] = null } - entry.resume() } +} - [MKDIR] (dir, mode) { +class WriteStreamSync extends WriteStream { + [_open] () { + let fd try { - return mkdir.sync(dir, { - uid: this.uid, - gid: this.gid, - processUid: this.processUid, - processGid: this.processGid, - umask: this.processUmask, - preserve: this.preservePaths, - unlink: this.unlink, - cache: this.dirCache, - cwd: this.cwd, - mode: mode - }) + fd = fs.openSync(this[_path], this[_flags], this[_mode]) } catch (er) { - return er + if (this[_defaultFlag] && + this[_flags] === 'r+' && + er && er.code === 'ENOENT') { + this[_flags] = 'w' + return this[_open]() + } else + throw er } + this[_onopen](null, fd) } - [LINK] (entry, linkpath, link) { + [_close] () { + if (this[_autoClose] && typeof this[_fd] === 'number') { + try { + fs.closeSync(this[_fd]) + } catch (er) {} + this[_fd] = null + this.emit('close') + } + } + + [_write] (buf) { try { - fs[link + 'Sync'](linkpath, entry.absolute) - entry.resume() + this[_onwrite](null, + fs.writeSync(this[_fd], buf, 0, buf.length, this[_pos])) } catch (er) { - return this[ONERROR](er, entry) + this[_onwrite](er, 0) } } } -Unpack.Sync = UnpackSync -module.exports = Unpack +const writev = (fd, iovec, pos, cb) => { + const done = (er, bw) => cb(er, bw, iovec) + const req = new FSReqWrap() + req.oncomplete = done + binding.writeBuffers(fd, iovec, pos, req) +} + +exports.ReadStream = ReadStream +exports.ReadStreamSync = ReadStreamSync + +exports.WriteStream = WriteStream +exports.WriteStreamSync = WriteStreamSync /***/ }), -/* 305 */ +/* 301 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -// wrapper around mkdirp for tar's needs. -// TODO: This should probably be a class, not functionally -// passing around state in a gazillion args. +const Buffer = __webpack_require__(282) -const mkdirp = __webpack_require__(182) +// XXX: This shares a lot in common with extract.js +// maybe some DRY opportunity here? + +// tar -t +const hlo = __webpack_require__(280) +const Parser = __webpack_require__(302) const fs = __webpack_require__(4) +const fsm = __webpack_require__(300) const path = __webpack_require__(20) -const chownr = __webpack_require__(306) -class SymlinkError extends Error { - constructor (symlink, path) { - super('Cannot extract through symbolic link') - this.path = path - this.symlink = symlink - } +const t = module.exports = (opt_, files, cb) => { + if (typeof opt_ === 'function') + cb = opt_, files = null, opt_ = {} + else if (Array.isArray(opt_)) + files = opt_, opt_ = {} - get name () { - return 'SylinkError' - } -} + if (typeof files === 'function') + cb = files, files = null -class CwdError extends Error { - constructor (path, code) { - super(code + ': Cannot cd into \'' + path + '\'') - this.path = path - this.code = code - } + if (!files) + files = [] + else + files = Array.from(files) - get name () { - return 'CwdError' - } -} + const opt = hlo(opt_) -const mkdir = module.exports = (dir, opt, cb) => { - // if there's any overlap between mask and mode, - // then we'll need an explicit chmod - const umask = opt.umask - const mode = opt.mode | 0o0700 - const needChmod = (mode & umask) !== 0 + if (opt.sync && typeof cb === 'function') + throw new TypeError('callback not supported for sync tar functions') - const uid = opt.uid - const gid = opt.gid - const doChown = typeof uid === 'number' && - typeof gid === 'number' && - ( uid !== opt.processUid || gid !== opt.processGid ) + if (!opt.file && typeof cb === 'function') + throw new TypeError('callback only supported with file option') - const preserve = opt.preserve - const unlink = opt.unlink - const cache = opt.cache - const cwd = opt.cwd + if (files.length) + filesFilter(opt, files) - const done = (er, created) => { - if (er) - cb(er) - else { - cache.set(dir, true) - if (created && doChown) - chownr(created, uid, gid, er => done(er)) - else if (needChmod) - fs.chmod(dir, mode, cb) - else - cb() - } - } + if (!opt.noResume) + onentryFunction(opt) - if (cache && cache.get(dir) === true) - return done() + return opt.file && opt.sync ? listFileSync(opt) + : opt.file ? listFile(opt, cb) + : list(opt) +} - if (dir === cwd) - return fs.stat(dir, (er, st) => { - if (er || !st.isDirectory()) - er = new CwdError(dir, er && er.code || 'ENOTDIR') - done(er) - }) +const onentryFunction = opt => { + const onentry = opt.onentry + opt.onentry = onentry ? e => { + onentry(e) + e.resume() + } : e => e.resume() +} - if (preserve) - return mkdirp(dir, mode, done) +// construct a filter that limits the file entries listed +// include child entries if a dir is included +const filesFilter = (opt, files) => { + const map = new Map(files.map(f => [f.replace(/\/+$/, ''), true])) + const filter = opt.filter - const sub = path.relative(cwd, dir) - const parts = sub.split(/\/|\\/) - mkdir_(cwd, parts, mode, cache, unlink, cwd, null, done) + const mapHas = (file, r) => { + const root = r || path.parse(file).root || '.' + const ret = file === root ? false + : map.has(file) ? map.get(file) + : mapHas(path.dirname(file), root) + + map.set(file, ret) + return ret + } + + opt.filter = filter + ? (file, entry) => filter(file, entry) && mapHas(file.replace(/\/+$/, '')) + : file => mapHas(file.replace(/\/+$/, '')) } -const mkdir_ = (base, parts, mode, cache, unlink, cwd, created, cb) => { - if (!parts.length) - return cb(null, created) - const p = parts.shift() - const part = base + '/' + p - if (cache.get(part)) - return mkdir_(part, parts, mode, cache, unlink, cwd, created, cb) - fs.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb)) +const listFileSync = opt => { + const p = list(opt) + const file = opt.file + let threw = true + let fd + try { + const stat = fs.statSync(file) + const readSize = opt.maxReadSize || 16*1024*1024 + if (stat.size < readSize) { + p.end(fs.readFileSync(file)) + } else { + let pos = 0 + const buf = Buffer.allocUnsafe(readSize) + fd = fs.openSync(file, 'r') + while (pos < stat.size) { + let bytesRead = fs.readSync(fd, buf, 0, readSize, pos) + pos += bytesRead + p.write(buf.slice(0, bytesRead)) + } + p.end() + } + threw = false + } finally { + if (threw && fd) + try { fs.closeSync(fd) } catch (er) {} + } } -const onmkdir = (part, parts, mode, cache, unlink, cwd, created, cb) => er => { - if (er) { - if (er.path && path.dirname(er.path) === cwd && - (er.code === 'ENOTDIR' || er.code === 'ENOENT')) - return cb(new CwdError(cwd, er.code)) +const listFile = (opt, cb) => { + const parse = new Parser(opt) + const readSize = opt.maxReadSize || 16*1024*1024 - fs.lstat(part, (statEr, st) => { - if (statEr) - cb(statEr) - else if (st.isDirectory()) - mkdir_(part, parts, mode, cache, unlink, cwd, created, cb) - else if (unlink) - fs.unlink(part, er => { - if (er) - return cb(er) - fs.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb)) + const file = opt.file + const p = new Promise((resolve, reject) => { + parse.on('error', reject) + parse.on('end', resolve) + + fs.stat(file, (er, stat) => { + if (er) + reject(er) + else { + const stream = new fsm.ReadStream(file, { + readSize: readSize, + size: stat.size }) - else if (st.isSymbolicLink()) - return cb(new SymlinkError(part, part + '/' + parts.join('/'))) - else - cb(er) + stream.on('error', reject) + stream.pipe(parse) + } }) - } else { - created = created || part - mkdir_(part, parts, mode, cache, unlink, cwd, created, cb) - } + }) + return cb ? p.then(cb, cb) : p } -const mkdirSync = module.exports.sync = (dir, opt) => { - // if there's any overlap between mask and mode, - // then we'll need an explicit chmod - const umask = opt.umask - const mode = opt.mode | 0o0700 - const needChmod = (mode & umask) !== 0 - - const uid = opt.uid - const gid = opt.gid - const doChown = typeof uid === 'number' && - typeof gid === 'number' && - ( uid !== opt.processUid || gid !== opt.processGid ) - - const preserve = opt.preserve - const unlink = opt.unlink - const cache = opt.cache - const cwd = opt.cwd +const list = opt => new Parser(opt) - const done = (created) => { - cache.set(dir, true) - if (created && doChown) - chownr.sync(created, uid, gid) - if (needChmod) - fs.chmodSync(dir, mode) - } - if (cache && cache.get(dir) === true) - return done() +/***/ }), +/* 302 */ +/***/ (function(module, exports, __webpack_require__) { - if (dir === cwd) { - let ok = false - let code = 'ENOTDIR' - try { - ok = fs.statSync(dir).isDirectory() - } catch (er) { - code = er.code - } finally { - if (!ok) - throw new CwdError(dir, code) - } - done() - return - } +"use strict"; - if (preserve) - return done(mkdirp.sync(dir, mode)) - const sub = path.relative(cwd, dir) - const parts = sub.split(/\/|\\/) - let created = null - for (let p = parts.shift(), part = cwd; - p && (part += '/' + p); - p = parts.shift()) { +// this[BUFFER] is the remainder of a chunk if we're waiting for +// the full 512 bytes of a header to come in. We will Buffer.concat() +// it to the next write(), which is a mem copy, but a small one. +// +// this[QUEUE] is a Yallist of entries that haven't been emitted +// yet this can only get filled up if the user keeps write()ing after +// a write() returns false, or does a write() with more than one entry +// +// We don't buffer chunks, we always parse them and either create an +// entry, or push it into the active entry. The ReadEntry class knows +// to throw data away if .ignore=true +// +// Shift entry off the buffer when it emits 'end', and emit 'entry' for +// the next one in the list. +// +// At any time, we're pushing body chunks into the entry at WRITEENTRY, +// and waiting for 'end' on the entry at READENTRY +// +// ignored entries get .resume() called on them straight away - if (cache.get(part)) - continue +const warner = __webpack_require__(297) +const path = __webpack_require__(20) +const Header = __webpack_require__(295) +const EE = __webpack_require__(137) +const Yallist = __webpack_require__(286) +const maxMetaEntrySize = 1024 * 1024 +const Entry = __webpack_require__(291) +const Pax = __webpack_require__(294) +const zlib = __webpack_require__(289) +const Buffer = __webpack_require__(282) - try { - fs.mkdirSync(part, mode) - created = created || part - cache.set(part, true) - } catch (er) { - if (er.path && path.dirname(er.path) === cwd && - (er.code === 'ENOTDIR' || er.code === 'ENOENT')) - return new CwdError(cwd, er.code) +const gzipHeader = Buffer.from([0x1f, 0x8b]) +const STATE = Symbol('state') +const WRITEENTRY = Symbol('writeEntry') +const READENTRY = Symbol('readEntry') +const NEXTENTRY = Symbol('nextEntry') +const PROCESSENTRY = Symbol('processEntry') +const EX = Symbol('extendedHeader') +const GEX = Symbol('globalExtendedHeader') +const META = Symbol('meta') +const EMITMETA = Symbol('emitMeta') +const BUFFER = Symbol('buffer') +const QUEUE = Symbol('queue') +const ENDED = Symbol('ended') +const EMITTEDEND = Symbol('emittedEnd') +const EMIT = Symbol('emit') +const UNZIP = Symbol('unzip') +const CONSUMECHUNK = Symbol('consumeChunk') +const CONSUMECHUNKSUB = Symbol('consumeChunkSub') +const CONSUMEBODY = Symbol('consumeBody') +const CONSUMEMETA = Symbol('consumeMeta') +const CONSUMEHEADER = Symbol('consumeHeader') +const CONSUMING = Symbol('consuming') +const BUFFERCONCAT = Symbol('bufferConcat') +const MAYBEEND = Symbol('maybeEnd') +const WRITING = Symbol('writing') +const ABORTED = Symbol('aborted') +const DONE = Symbol('onDone') - const st = fs.lstatSync(part) - if (st.isDirectory()) { - cache.set(part, true) - continue - } else if (unlink) { - fs.unlinkSync(part) - fs.mkdirSync(part, mode) - created = created || part - cache.set(part, true) - continue - } else if (st.isSymbolicLink()) - return new SymlinkError(part, part + '/' + parts.join('/')) - } - } +const noop = _ => true - return done(created) -} +module.exports = warner(class Parser extends EE { + constructor (opt) { + opt = opt || {} + super(opt) + if (opt.ondone) + this.on(DONE, opt.ondone) + else + this.on(DONE, _ => { + this.emit('prefinish') + this.emit('finish') + this.emit('end') + this.emit('close') + }) -/***/ }), -/* 306 */ -/***/ (function(module, exports, __webpack_require__) { + this.strict = !!opt.strict + this.maxMetaEntrySize = opt.maxMetaEntrySize || maxMetaEntrySize + this.filter = typeof opt.filter === 'function' ? opt.filter : noop -"use strict"; + // have to set this so that streams are ok piping into it + this.writable = true + this.readable = false -const fs = __webpack_require__(4) -const path = __webpack_require__(20) + this[QUEUE] = new Yallist() + this[BUFFER] = null + this[READENTRY] = null + this[WRITEENTRY] = null + this[STATE] = 'begin' + this[META] = '' + this[EX] = null + this[GEX] = null + this[ENDED] = false + this[UNZIP] = null + this[ABORTED] = false + if (typeof opt.onwarn === 'function') + this.on('warn', opt.onwarn) + if (typeof opt.onentry === 'function') + this.on('entry', opt.onentry) + } -/* istanbul ignore next */ -const LCHOWN = fs.lchown ? 'lchown' : 'chown' -/* istanbul ignore next */ -const LCHOWNSYNC = fs.lchownSync ? 'lchownSync' : 'chownSync' + [CONSUMEHEADER] (chunk, position) { + const header = new Header(chunk, position, this[EX], this[GEX]) -// fs.readdir could only accept an options object as of node v6 -const nodeVersion = process.version -let readdir = (path, options, cb) => fs.readdir(path, options, cb) -let readdirSync = (path, options) => fs.readdirSync(path, options) -/* istanbul ignore next */ -if (/^v4\./.test(nodeVersion)) - readdir = (path, options, cb) => fs.readdir(path, cb) + if (header.nullBlock) + this[EMIT]('nullBlock') + else if (!header.cksumValid) + this.warn('invalid entry', header) + else if (!header.path) + this.warn('invalid: path is required', header) + else { + const type = header.type + if (/^(Symbolic)?Link$/.test(type) && !header.linkpath) + this.warn('invalid: linkpath required', header) + else if (!/^(Symbolic)?Link$/.test(type) && header.linkpath) + this.warn('invalid: linkpath forbidden', header) + else { + const entry = this[WRITEENTRY] = new Entry(header, this[EX], this[GEX]) -const chownrKid = (p, child, uid, gid, cb) => { - if (typeof child === 'string') - return fs.lstat(path.resolve(p, child), (er, stats) => { - if (er) - return cb(er) - stats.name = child - chownrKid(p, stats, uid, gid, cb) - }) + if (entry.meta) { + if (entry.size > this.maxMetaEntrySize) { + entry.ignore = true + this[EMIT]('ignoredEntry', entry) + this[STATE] = 'ignore' + } else if (entry.size > 0) { + this[META] = '' + entry.on('data', c => this[META] += c) + this[STATE] = 'meta' + } + } else { - if (child.isDirectory()) { - chownr(path.resolve(p, child.name), uid, gid, er => { - if (er) - return cb(er) - fs[LCHOWN](path.resolve(p, child.name), uid, gid, cb) - }) - } else - fs[LCHOWN](path.resolve(p, child.name), uid, gid, cb) -} + this[EX] = null + entry.ignore = entry.ignore || !this.filter(entry.path, entry) + if (entry.ignore) { + this[EMIT]('ignoredEntry', entry) + this[STATE] = entry.remain ? 'ignore' : 'begin' + } else { + if (entry.remain) + this[STATE] = 'body' + else { + this[STATE] = 'begin' + entry.end() + } + if (!this[READENTRY]) { + this[QUEUE].push(entry) + this[NEXTENTRY]() + } else + this[QUEUE].push(entry) + } + } + } + } + } -const chownr = (p, uid, gid, cb) => { - readdir(p, { withFileTypes: true }, (er, children) => { - // any error other than ENOTDIR or ENOTSUP means it's not readable, - // or doesn't exist. give up. - if (er && er.code !== 'ENOTDIR' && er.code !== 'ENOTSUP') - return cb(er) - if (er || !children.length) return fs[LCHOWN](p, uid, gid, cb) + [PROCESSENTRY] (entry) { + let go = true - let len = children.length - let errState = null - const then = er => { - if (errState) return - if (er) return cb(errState = er) - if (-- len === 0) return fs[LCHOWN](p, uid, gid, cb) + if (!entry) { + this[READENTRY] = null + go = false + } else if (Array.isArray(entry)) + this.emit.apply(this, entry) + else { + this[READENTRY] = entry + this.emit('entry', entry) + if (!entry.emittedEnd) { + entry.on('end', _ => this[NEXTENTRY]()) + go = false + } } - children.forEach(child => chownrKid(p, child, uid, gid, then)) - }) -} + return go + } -const chownrKidSync = (p, child, uid, gid) => { - if (typeof child === 'string') { - const stats = fs.lstatSync(path.resolve(p, child)) - stats.name = child - child = stats + [NEXTENTRY] () { + do {} while (this[PROCESSENTRY](this[QUEUE].shift())) + + if (!this[QUEUE].length) { + // At this point, there's nothing in the queue, but we may have an + // entry which is being consumed (readEntry). + // If we don't, then we definitely can handle more data. + // If we do, and either it's flowing, or it has never had any data + // written to it, then it needs more. + // The only other possibility is that it has returned false from a + // write() call, so we wait for the next drain to continue. + const re = this[READENTRY] + const drainNow = !re || re.flowing || re.size === re.remain + if (drainNow) { + if (!this[WRITING]) + this.emit('drain') + } else + re.once('drain', _ => this.emit('drain')) + } } - if (child.isDirectory()) - chownrSync(path.resolve(p, child.name), uid, gid) + [CONSUMEBODY] (chunk, position) { + // write up to but no more than writeEntry.blockRemain + const entry = this[WRITEENTRY] + const br = entry.blockRemain + const c = (br >= chunk.length && position === 0) ? chunk + : chunk.slice(position, position + br) - fs[LCHOWNSYNC](path.resolve(p, child.name), uid, gid) -} + entry.write(c) -const chownrSync = (p, uid, gid) => { - let children - try { - children = readdirSync(p, { withFileTypes: true }) - } catch (er) { - if (er && er.code === 'ENOTDIR' && er.code !== 'ENOTSUP') - return fs[LCHOWNSYNC](p, uid, gid) - throw er + if (!entry.blockRemain) { + this[STATE] = 'begin' + this[WRITEENTRY] = null + entry.end() + } + + return c.length } - if (children.length) - children.forEach(child => chownrKidSync(p, child, uid, gid)) + [CONSUMEMETA] (chunk, position) { + const entry = this[WRITEENTRY] + const ret = this[CONSUMEBODY](chunk, position) - return fs[LCHOWNSYNC](p, uid, gid) -} + // if we finished, then the entry is reset + if (!this[WRITEENTRY]) + this[EMITMETA](entry) -module.exports = chownr -chownr.sync = chownrSync + return ret + } + [EMIT] (ev, data, extra) { + if (!this[QUEUE].length && !this[READENTRY]) + this.emit(ev, data, extra) + else + this[QUEUE].push([ev, data, extra]) + } -/***/ }), -/* 307 */ -/***/ (function(module, exports, __webpack_require__) { + [EMITMETA] (entry) { + this[EMIT]('meta', this[META]) + switch (entry.type) { + case 'ExtendedHeader': + case 'OldExtendedHeader': + this[EX] = Pax.parse(this[META], this[EX], false) + break -"use strict"; + case 'GlobalExtendedHeader': + this[GEX] = Pax.parse(this[META], this[GEX], true) + break -Object.defineProperty(exports, "__esModule", { value: true }); -const tslib_1 = __webpack_require__(3); -const follow_redirects_1 = __webpack_require__(269); -const tunnel_1 = tslib_1.__importDefault(__webpack_require__(308)); -const url_1 = __webpack_require__(267); -const zlib_1 = tslib_1.__importDefault(__webpack_require__(82)); -const is_1 = __webpack_require__(194); -const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const logger = __webpack_require__(2)('model-fetch'); -function getAgent(endpoint) { - let key = endpoint.protocol.startsWith('https') ? 'HTTPS_PROXY' : 'HTTP_PROXY'; - let env = process.env[key] || process.env[key.toLowerCase()]; - if (env) { - let noProxy = process.env.NO_PROXY || process.env.no_proxy; - if (noProxy === '*') { - env = null; - } - else if (noProxy) { - // canonicalize the hostname, so that 'oogle.com' won't match 'google.com' - const hostname = endpoint.hostname.replace(/^\.*/, '.').toLowerCase(); - const port = endpoint.port || endpoint.protocol.startsWith('https') ? '443' : '80'; - const noProxyList = noProxy.split(','); - for (let i = 0, len = noProxyList.length; i < len; i++) { - let noProxyItem = noProxyList[i].trim().toLowerCase(); - // no_proxy can be granular at the port level, which complicates things a bit. - if (noProxyItem.indexOf(':') > -1) { - let noProxyItemParts = noProxyItem.split(':', 2); - let noProxyHost = noProxyItemParts[0].replace(/^\.*/, '.'); - let noProxyPort = noProxyItemParts[1]; - if (port === noProxyPort && hostname.endsWith(noProxyHost)) { - env = null; - break; - } - } - else { - noProxyItem = noProxyItem.replace(/^\.*/, '.'); - if (hostname.endsWith(noProxyItem)) { - env = null; - break; - } - } - } - } + case 'NextFileHasLongPath': + case 'OldGnuLongPath': + this[EX] = this[EX] || Object.create(null) + this[EX].path = this[META].replace(/\0.*/, '') + break + + case 'NextFileHasLongLinkpath': + this[EX] = this[EX] || Object.create(null) + this[EX].linkpath = this[META].replace(/\0.*/, '') + break + + /* istanbul ignore next */ + default: throw new Error('unknown meta: ' + entry.type) } - let proxy = workspace_1.default.getConfiguration('http').get('proxy', ''); - if (!proxy && env) { - proxy = env; + } + + abort (msg, error) { + this[ABORTED] = true + this.warn(msg, error) + this.emit('abort', error) + this.emit('error', error) + } + + write (chunk) { + if (this[ABORTED]) + return + + // first write, might be gzipped + if (this[UNZIP] === null && chunk) { + if (this[BUFFER]) { + chunk = Buffer.concat([this[BUFFER], chunk]) + this[BUFFER] = null + } + if (chunk.length < gzipHeader.length) { + this[BUFFER] = chunk + return true + } + for (let i = 0; this[UNZIP] === null && i < gzipHeader.length; i++) { + if (chunk[i] !== gzipHeader[i]) + this[UNZIP] = false + } + if (this[UNZIP] === null) { + const ended = this[ENDED] + this[ENDED] = false + this[UNZIP] = new zlib.Unzip() + this[UNZIP].on('data', chunk => this[CONSUMECHUNK](chunk)) + this[UNZIP].on('error', er => + this.abort(er.message, er)) + this[UNZIP].on('end', _ => { + this[ENDED] = true + this[CONSUMECHUNK]() + }) + this[WRITING] = true + const ret = this[UNZIP][ended ? 'end' : 'write' ](chunk) + this[WRITING] = false + return ret + } } - if (proxy) { - proxy = proxy.replace(/^https?:\/\//, '').replace(/\/$/, ''); - let auth = proxy.includes('@') ? proxy.split('@', 2)[0] : ''; - let parts = auth.length ? proxy.slice(auth.length + 1).split(':') : proxy.split(':'); - logger.info(`Using proxy from: ${proxy}`); - if (parts.length > 1) { - let agent = tunnel_1.default.httpsOverHttp({ - proxy: { - headers: {}, - host: parts[0], - port: parseInt(parts[1], 10), - proxyAuth: auth - } - }); - return agent; - } + + this[WRITING] = true + if (this[UNZIP]) + this[UNZIP].write(chunk) + else + this[CONSUMECHUNK](chunk) + this[WRITING] = false + + // return false if there's a queue, or if the current entry isn't flowing + const ret = + this[QUEUE].length ? false : + this[READENTRY] ? this[READENTRY].flowing : + true + + // if we have no queue, then that means a clogged READENTRY + if (!ret && !this[QUEUE].length) + this[READENTRY].once('drain', _ => this.emit('drain')) + + return ret + } + + [BUFFERCONCAT] (c) { + if (c && !this[ABORTED]) + this[BUFFER] = this[BUFFER] ? Buffer.concat([this[BUFFER], c]) : c + } + + [MAYBEEND] () { + if (this[ENDED] && + !this[EMITTEDEND] && + !this[ABORTED] && + !this[CONSUMING]) { + this[EMITTEDEND] = true + const entry = this[WRITEENTRY] + if (entry && entry.blockRemain) { + const have = this[BUFFER] ? this[BUFFER].length : 0 + this.warn('Truncated input (needed ' + entry.blockRemain + + ' more bytes, only ' + have + ' available)', entry) + if (this[BUFFER]) + entry.write(this[BUFFER]) + entry.end() + } + this[EMIT](DONE) } -} -exports.getAgent = getAgent; -/** - * Fetch text from server - */ -function fetch(url, data, options = {}) { - logger.info('fetch:', url); - let mod = url.startsWith('https') ? follow_redirects_1.https : follow_redirects_1.http; - let endpoint = url_1.parse(url); - let agent = getAgent(endpoint); - let opts = Object.assign({ - method: 'GET', - hostname: endpoint.hostname, - port: endpoint.port ? parseInt(endpoint.port, 10) : (endpoint.protocol === 'https:' ? 443 : 80), - path: endpoint.path, - protocol: url.startsWith('https') ? 'https:' : 'http:', - agent, - headers: { - 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64)', - 'Accept-Encoding': 'gzip' - } - }, options); - if (data && is_1.objectLiteral(data)) { - opts.headers['Content-Type'] = 'application/json'; + } + + [CONSUMECHUNK] (chunk) { + if (this[CONSUMING]) { + this[BUFFERCONCAT](chunk) + } else if (!chunk && !this[BUFFER]) { + this[MAYBEEND]() + } else { + this[CONSUMING] = true + if (this[BUFFER]) { + this[BUFFERCONCAT](chunk) + const c = this[BUFFER] + this[BUFFER] = null + this[CONSUMECHUNKSUB](c) + } else { + this[CONSUMECHUNKSUB](chunk) + } + + while (this[BUFFER] && this[BUFFER].length >= 512 && !this[ABORTED]) { + const c = this[BUFFER] + this[BUFFER] = null + this[CONSUMECHUNKSUB](c) + } + this[CONSUMING] = false } - if (data && !opts.method) { - opts.method = 'POST'; + + if (!this[BUFFER] || this[ENDED]) + this[MAYBEEND]() + } + + [CONSUMECHUNKSUB] (chunk) { + // we know that we are in CONSUMING mode, so anything written goes into + // the buffer. Advance the position and put any remainder in the buffer. + let position = 0 + let length = chunk.length + while (position + 512 <= length && !this[ABORTED]) { + switch (this[STATE]) { + case 'begin': + this[CONSUMEHEADER](chunk, position) + position += 512 + break + + case 'ignore': + case 'body': + position += this[CONSUMEBODY](chunk, position) + break + + case 'meta': + position += this[CONSUMEMETA](chunk, position) + break + + /* istanbul ignore next */ + default: + throw new Error('invalid state: ' + this[STATE]) + } } - return new Promise((resolve, reject) => { - // tslint:disable-next-line: only-arrow-functions - try { - const req = mod.request(opts, res => { - let readable = res; - if (res.statusCode != 200) { - reject(new Error(`Invalid response from ${url}: ${res.statusCode}`)); - return; - } - let chunks = []; - let contentType = res.headers['content-type']; - let contentEncoding = res.headers['content-encoding']; - let ms = contentType.match(/charset=(\S+)/); - let encoding = ms ? ms[1] : 'utf8'; - if (contentEncoding == 'gzip') { - const unzip = zlib_1.default.createGunzip(); - readable = res.pipe(unzip); - } - readable.on('data', chunk => { - chunks.push(chunk); - }); - readable.on('end', () => { - let buf = Buffer.concat(chunks); - let rawData = buf.toString(encoding); - if (/^application\/json/.test(contentType)) { - try { - const parsedData = JSON.parse(rawData); - resolve(parsedData); - } - catch (e) { - reject(`Parse error: ${e}`); - } - } - else { - resolve(rawData); - } - }); - }); - req.on('error', reject); - if (data) { - if (typeof data == 'string') { - req.write(data); - } - else { - req.write(JSON.stringify(data)); - } - } - req.end(); - } - catch (e) { - logger.error(e); - reject(e); - } - }); -} -exports.default = fetch; -//# sourceMappingURL=fetch.js.map -/***/ }), -/* 308 */ -/***/ (function(module, exports, __webpack_require__) { + if (position < length) { + if (this[BUFFER]) + this[BUFFER] = Buffer.concat([chunk.slice(position), this[BUFFER]]) + else + this[BUFFER] = chunk.slice(position) + } + } -module.exports = __webpack_require__(309); + end (chunk) { + if (!this[ABORTED]) { + if (this[UNZIP]) + this[UNZIP].end(chunk) + else { + this[ENDED] = true + this.write(chunk) + } + } + } +}) /***/ }), -/* 309 */ +/* 303 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const Buffer = __webpack_require__(282) -var net = __webpack_require__(96); -var tls = __webpack_require__(310); -var http = __webpack_require__(270); -var https = __webpack_require__(271); -var events = __webpack_require__(137); -var assert = __webpack_require__(46); -var util = __webpack_require__(12); +// tar -r +const hlo = __webpack_require__(280) +const Pack = __webpack_require__(281) +const Parse = __webpack_require__(302) +const fs = __webpack_require__(4) +const fsm = __webpack_require__(300) +const t = __webpack_require__(301) +const path = __webpack_require__(20) +// starting at the head of the file, read a Header +// If the checksum is invalid, that's our position to start writing +// If it is, jump forward by the specified size (round up to 512) +// and try again. +// Write the new Pack stream starting there. -exports.httpOverHttp = httpOverHttp; -exports.httpsOverHttp = httpsOverHttp; -exports.httpOverHttps = httpOverHttps; -exports.httpsOverHttps = httpsOverHttps; +const Header = __webpack_require__(295) +const r = module.exports = (opt_, files, cb) => { + const opt = hlo(opt_) -function httpOverHttp(options) { - var agent = new TunnelingAgent(options); - agent.request = http.request; - return agent; -} + if (!opt.file) + throw new TypeError('file is required') -function httpsOverHttp(options) { - var agent = new TunnelingAgent(options); - agent.request = http.request; - agent.createSocket = createSecureSocket; - agent.defaultPort = 443; - return agent; -} + if (opt.gzip) + throw new TypeError('cannot append to compressed archives') -function httpOverHttps(options) { - var agent = new TunnelingAgent(options); - agent.request = https.request; - return agent; -} + if (!files || !Array.isArray(files) || !files.length) + throw new TypeError('no files or directories specified') -function httpsOverHttps(options) { - var agent = new TunnelingAgent(options); - agent.request = https.request; - agent.createSocket = createSecureSocket; - agent.defaultPort = 443; - return agent; + files = Array.from(files) + + return opt.sync ? replaceSync(opt, files) + : replace(opt, files, cb) } +const replaceSync = (opt, files) => { + const p = new Pack.Sync(opt) -function TunnelingAgent(options) { - var self = this; - self.options = options || {}; - self.proxyOptions = self.options.proxy || {}; - self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; - self.requests = []; - self.sockets = []; + let threw = true + let fd + let position - self.on('free', function onFree(socket, host, port, localAddress) { - var options = toOptions(host, port, localAddress); - for (var i = 0, len = self.requests.length; i < len; ++i) { - var pending = self.requests[i]; - if (pending.host === options.host && pending.port === options.port) { - // Detect the request to connect same origin server, - // reuse the connection. - self.requests.splice(i, 1); - pending.request.onSocket(socket); - return; - } + try { + try { + fd = fs.openSync(opt.file, 'r+') + } catch (er) { + if (er.code === 'ENOENT') + fd = fs.openSync(opt.file, 'w+') + else + throw er } - socket.destroy(); - self.removeSocket(socket); - }); -} -util.inherits(TunnelingAgent, events.EventEmitter); -TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { - var self = this; - var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); + const st = fs.fstatSync(fd) + const headBuf = Buffer.alloc(512) - if (self.sockets.length >= this.maxSockets) { - // We are over limit so we'll add it to the queue. - self.requests.push(options); - return; - } + POSITION: for (position = 0; position < st.size; position += 512) { + for (let bufPos = 0, bytes = 0; bufPos < 512; bufPos += bytes) { + bytes = fs.readSync( + fd, headBuf, bufPos, headBuf.length - bufPos, position + bufPos + ) - // If we are under maxSockets create a new one. - self.createSocket(options, function(socket) { - socket.on('free', onFree); - socket.on('close', onCloseOrRemove); - socket.on('agentRemove', onCloseOrRemove); - req.onSocket(socket); + if (position === 0 && headBuf[0] === 0x1f && headBuf[1] === 0x8b) + throw new Error('cannot append to compressed archives') - function onFree() { - self.emit('free', socket, options); - } + if (!bytes) + break POSITION + } - function onCloseOrRemove(err) { - self.removeSocket(socket); - socket.removeListener('free', onFree); - socket.removeListener('close', onCloseOrRemove); - socket.removeListener('agentRemove', onCloseOrRemove); + let h = new Header(headBuf) + if (!h.cksumValid) + break + let entryBlockSize = 512 * Math.ceil(h.size / 512) + if (position + entryBlockSize + 512 > st.size) + break + // the 512 for the header we just parsed will be added as well + // also jump ahead all the blocks for the body + position += entryBlockSize + if (opt.mtimeCache) + opt.mtimeCache.set(h.path, h.mtime) } - }); -}; - -TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { - var self = this; - var placeholder = {}; - self.sockets.push(placeholder); + threw = false - var connectOptions = mergeOptions({}, self.proxyOptions, { - method: 'CONNECT', - path: options.host + ':' + options.port, - agent: false, - headers: { - host: options.host + ':' + options.port - } - }); - if (options.localAddress) { - connectOptions.localAddress = options.localAddress; - } - if (connectOptions.proxyAuth) { - connectOptions.headers = connectOptions.headers || {}; - connectOptions.headers['Proxy-Authorization'] = 'Basic ' + - new Buffer(connectOptions.proxyAuth).toString('base64'); + streamSync(opt, p, position, fd, files) + } finally { + if (threw) + try { fs.closeSync(fd) } catch (er) {} } +} - debug('making CONNECT request'); - var connectReq = self.request(connectOptions); - connectReq.useChunkedEncodingByDefault = false; // for v0.6 - connectReq.once('response', onResponse); // for v0.6 - connectReq.once('upgrade', onUpgrade); // for v0.6 - connectReq.once('connect', onConnect); // for v0.7 or later - connectReq.once('error', onError); - connectReq.end(); +const streamSync = (opt, p, position, fd, files) => { + const stream = new fsm.WriteStreamSync(opt.file, { + fd: fd, + start: position + }) + p.pipe(stream) + addFilesSync(p, files) +} - function onResponse(res) { - // Very hacky. This is necessary to avoid http-parser leaks. - res.upgrade = true; - } +const replace = (opt, files, cb) => { + files = Array.from(files) + const p = new Pack(opt) - function onUpgrade(res, socket, head) { - // Hacky. - process.nextTick(function() { - onConnect(res, socket, head); - }); - } + const getPos = (fd, size, cb_) => { + const cb = (er, pos) => { + if (er) + fs.close(fd, _ => cb_(er)) + else + cb_(null, pos) + } - function onConnect(res, socket, head) { - connectReq.removeAllListeners(); - socket.removeAllListeners(); - - if (res.statusCode !== 200) { - debug('tunneling socket could not be established, statusCode=%d', - res.statusCode); - socket.destroy(); - var error = new Error('tunneling socket could not be established, ' + - 'statusCode=' + res.statusCode); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - return; - } - if (head.length > 0) { - debug('got illegal response body from proxy'); - socket.destroy(); - var error = new Error('got illegal response body from proxy'); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - return; - } - debug('tunneling connection has established'); - self.sockets[self.sockets.indexOf(placeholder)] = socket; - return cb(socket); - } - - function onError(cause) { - connectReq.removeAllListeners(); + let position = 0 + if (size === 0) + return cb(null, 0) - debug('tunneling socket could not be established, cause=%s\n', - cause.message, cause.stack); - var error = new Error('tunneling socket could not be established, ' + - 'cause=' + cause.message); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - } -}; + let bufPos = 0 + const headBuf = Buffer.alloc(512) + const onread = (er, bytes) => { + if (er) + return cb(er) + bufPos += bytes + if (bufPos < 512 && bytes) + return fs.read( + fd, headBuf, bufPos, headBuf.length - bufPos, + position + bufPos, onread + ) -TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { - var pos = this.sockets.indexOf(socket) - if (pos === -1) { - return; - } - this.sockets.splice(pos, 1); + if (position === 0 && headBuf[0] === 0x1f && headBuf[1] === 0x8b) + return cb(new Error('cannot append to compressed archives')) - var pending = this.requests.shift(); - if (pending) { - // If we have pending requests and a socket gets closed a new one - // needs to be created to take over in the pool for the one that closed. - this.createSocket(pending, function(socket) { - pending.request.onSocket(socket); - }); - } -}; + // truncated header + if (bufPos < 512) + return cb(null, position) -function createSecureSocket(options, cb) { - var self = this; - TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { - var hostHeader = options.request.getHeader('host'); - var tlsOptions = mergeOptions({}, self.options, { - socket: socket, - servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host - }); + const h = new Header(headBuf) + if (!h.cksumValid) + return cb(null, position) - // 0 is dummy port for v0.6 - var secureSocket = tls.connect(0, tlsOptions); - self.sockets[self.sockets.indexOf(socket)] = secureSocket; - cb(secureSocket); - }); -} + const entryBlockSize = 512 * Math.ceil(h.size / 512) + if (position + entryBlockSize + 512 > size) + return cb(null, position) + position += entryBlockSize + 512 + if (position >= size) + return cb(null, position) -function toOptions(host, port, localAddress) { - if (typeof host === 'string') { // since v0.10 - return { - host: host, - port: port, - localAddress: localAddress - }; + if (opt.mtimeCache) + opt.mtimeCache.set(h.path, h.mtime) + bufPos = 0 + fs.read(fd, headBuf, 0, 512, position, onread) + } + fs.read(fd, headBuf, 0, 512, position, onread) } - return host; // for v0.11 or later -} -function mergeOptions(target) { - for (var i = 1, len = arguments.length; i < len; ++i) { - var overrides = arguments[i]; - if (typeof overrides === 'object') { - var keys = Object.keys(overrides); - for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { - var k = keys[j]; - if (overrides[k] !== undefined) { - target[k] = overrides[k]; - } + const promise = new Promise((resolve, reject) => { + p.on('error', reject) + let flag = 'r+' + const onopen = (er, fd) => { + if (er && er.code === 'ENOENT' && flag === 'r+') { + flag = 'w+' + return fs.open(opt.file, flag, onopen) } - } - } - return target; -} + if (er) + return reject(er) -var debug; -if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { - debug = function() { - var args = Array.prototype.slice.call(arguments); - if (typeof args[0] === 'string') { - args[0] = 'TUNNEL: ' + args[0]; - } else { - args.unshift('TUNNEL:'); + fs.fstat(fd, (er, st) => { + if (er) + return reject(er) + getPos(fd, st.size, (er, position) => { + if (er) + return reject(er) + const stream = new fsm.WriteStream(opt.file, { + fd: fd, + start: position + }) + p.pipe(stream) + stream.on('error', reject) + stream.on('close', resolve) + addFilesAsync(p, files) + }) + }) } - console.error.apply(console, args); - } -} else { - debug = function() {}; + fs.open(opt.file, flag, onopen) + }) + + return cb ? promise.then(cb, cb) : promise } -exports.debug = debug; // for test +const addFilesSync = (p, files) => { + files.forEach(file => { + if (file.charAt(0) === '@') + t({ + file: path.resolve(p.cwd, file.substr(1)), + sync: true, + noResume: true, + onentry: entry => p.add(entry) + }) + else + p.add(file) + }) + p.end() +} -/***/ }), -/* 310 */ -/***/ (function(module, exports) { +const addFilesAsync = (p, files) => { + while (files.length) { + const file = files.shift() + if (file.charAt(0) === '@') + return t({ + file: path.resolve(p.cwd, file.substr(1)), + noResume: true, + onentry: entry => p.add(entry) + }).then(_ => addFilesAsync(p, files)) + else + p.add(file) + } + p.end() +} -module.exports = require("tls"); /***/ }), -/* 311 */ +/* 304 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const tslib_1 = __webpack_require__(3); -const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); -const object_1 = __webpack_require__(193); -const logger = __webpack_require__(2)('model-memos'); -class Memos { - constructor(filepath) { - this.filepath = filepath; - if (!fs_1.default.existsSync(filepath)) { - fs_1.default.writeFileSync(filepath, '{}', 'utf8'); - } - } - fetchContent(id, key) { - try { - let content = fs_1.default.readFileSync(this.filepath, 'utf8'); - let res = JSON.parse(content); - let obj = res[id]; - if (!obj) - return undefined; - return obj[key]; - } - catch (e) { - return undefined; - } - } - async update(id, key, value) { - let { filepath } = this; - try { - let content = fs_1.default.readFileSync(filepath, 'utf8'); - let current = content ? JSON.parse(content) : {}; - current[id] = current[id] || {}; - if (value !== undefined) { - current[id][key] = object_1.deepClone(value); - } - else { - delete current[id][key]; - } - content = JSON.stringify(current, null, 2); - fs_1.default.writeFileSync(filepath, content, 'utf8'); - } - catch (e) { - logger.error(`Error on update memos:`, e); - } - } - createMemento(id) { - return { - get: (key, defaultValue) => { - let res = this.fetchContent(id, key); - return res === undefined ? defaultValue : res; - }, - update: async (key, value) => { - await this.update(id, key, value); - } - }; - } -} -exports.default = Memos; -//# sourceMappingURL=memos.js.map -/***/ }), -/* 312 */ -/***/ (function(module, exports, __webpack_require__) { +// tar -u -const logger = __webpack_require__(2)('extensions'); -/** - * Explicitly tells that promise should be run asynchonously. - */ -Promise.prototype.logError = function () { - // tslint:disable-next-line:no-empty - this.catch(e => { - logger.error(e); - }); -}; -//# sourceMappingURL=extensions.js.map +const hlo = __webpack_require__(280) +const r = __webpack_require__(303) +// just call tar.r with the filter and mtimeCache -/***/ }), -/* 313 */ -/***/ (function(module, exports, __webpack_require__) { +const u = module.exports = (opt_, files, cb) => { + const opt = hlo(opt_) -"use strict"; + if (!opt.file) + throw new TypeError('file is required') -Object.defineProperty(exports, "__esModule", { value: true }); -const tslib_1 = __webpack_require__(3); -const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); -const path = tslib_1.__importStar(__webpack_require__(20)); -const vm = tslib_1.__importStar(__webpack_require__(314)); -const lodash_1 = __webpack_require__(315); -const createLogger = __webpack_require__(2); -const logger = createLogger('util-factoroy'); -const requireFunc = true ? require : undefined; -const Module = __webpack_require__(316); -const REMOVED_GLOBALS = [ - 'reallyExit', - 'abort', - 'chdir', - 'umask', - 'setuid', - 'setgid', - 'setgroups', - '_fatalException', - 'exit', - 'kill', -]; -function removedGlobalStub(name) { - return () => { - throw new Error(`process.${name}() is not allowed in extension sandbox`); - }; -} -// @see node/lib/internal/module.js -function makeRequireFunction() { - const req = (p) => { - if (p === 'coc.nvim') { - return __webpack_require__(317); - } - return this.require(p); - }; - req.resolve = (request) => Module._resolveFilename(request, this); - req.main = process.mainModule; - // Enable support to add extra extension types - req.extensions = Module._extensions; - req.cache = Module._cache; - return req; -} -// @see node/lib/module.js -function compileInSandbox(sandbox) { - // eslint-disable-next-line - return function (content, filename) { - const require = makeRequireFunction.call(this); - const dirname = path.dirname(filename); - // remove shebang - // eslint-disable-next-line - const newContent = content.replace(/^\#\!.*/, ''); - const wrapper = Module.wrap(newContent); - const compiledWrapper = vm.runInContext(wrapper, sandbox, { filename }); - const args = [this.exports, require, this, filename, dirname]; - return compiledWrapper.apply(this.exports, args); - }; -} -function createSandbox(filename, logger) { - const module = new Module(filename); - module.paths = Module._nodeModulePaths(filename); - const sandbox = vm.createContext({ - module, - Buffer, - console: { - debug: (...args) => { - logger.debug.apply(logger, args); - }, - log: (...args) => { - logger.debug.apply(logger, args); - }, - error: (...args) => { - logger.error.apply(logger, args); - }, - info: (...args) => { - logger.info.apply(logger, args); - }, - warn: (...args) => { - logger.warn.apply(logger, args); - } - } - }); - lodash_1.defaults(sandbox, global); - sandbox.Reflect = Reflect; - sandbox.require = function sandboxRequire(p) { - const oldCompile = Module.prototype._compile; - Module.prototype._compile = compileInSandbox(sandbox); - const moduleExports = sandbox.module.require(p); - Module.prototype._compile = oldCompile; - return moduleExports; - }; - // patch `require` in sandbox to run loaded module in sandbox context - // if you need any of these, it might be worth discussing spawning separate processes - sandbox.process = new process.constructor(); - for (let key of Object.keys(process)) { - sandbox.process[key] = process[key]; - } - REMOVED_GLOBALS.forEach(name => { - sandbox.process[name] = removedGlobalStub(name); - }); - // read-only umask - sandbox.process.umask = (mask) => { - if (typeof mask !== 'undefined') { - throw new Error('Cannot use process.umask() to change mask (read-only)'); - } - return process.umask(); - }; - return sandbox; -} -// inspiration drawn from Module -function createExtension(id, filename) { - if (!fs_1.default.existsSync(filename)) { - // tslint:disable-next-line:no-empty - return { activate: () => { }, deactivate: null }; - } - const sandbox = createSandbox(filename, createLogger(`extension-${id}`)); - delete Module._cache[requireFunc.resolve(filename)]; - // attempt to import plugin - // Require plugin to export activate & deactivate - const defaultImport = sandbox.require(filename); - const activate = (defaultImport && defaultImport.activate) || defaultImport; - if (typeof activate !== 'function') { - // tslint:disable-next-line:no-empty - return { activate: () => { }, deactivate: null }; - } - return { - activate, - deactivate: typeof defaultImport.deactivate === 'function' ? defaultImport.deactivate : null - }; + if (opt.gzip) + throw new TypeError('cannot append to compressed archives') + + if (!files || !Array.isArray(files) || !files.length) + throw new TypeError('no files or directories specified') + + files = Array.from(files) + + mtimeFilter(opt) + return r(opt, files, cb) } -exports.createExtension = createExtension; -//# sourceMappingURL=factory.js.map -/***/ }), -/* 314 */ -/***/ (function(module, exports) { +const mtimeFilter = opt => { + const filter = opt.filter + + if (!opt.mtimeCache) + opt.mtimeCache = new Map() + + opt.filter = filter ? (path, stat) => + filter(path, stat) && !(opt.mtimeCache.get(path) > stat.mtime) + : (path, stat) => !(opt.mtimeCache.get(path) > stat.mtime) +} -module.exports = require("vm"); /***/ }), -/* 315 */ +/* 305 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -/** Used for built-in method references. */ -const objectProto = Object.prototype; -/** Used to check objects for own properties. */ -const hasOwnProperty = objectProto.hasOwnProperty; -/** - * Assigns own and inherited enumerable string keyed properties of source - * objects to the destination object for all destination properties that - * resolve to `undefined`. Source objects are applied from left to right. - * Once a property is set, additional values of the same property are ignored. - * - * **Note:** This method mutates `object`. - * - * @since 0.1.0 - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @returns {Object} Returns `object`. - * @see defaultsDeep - * @example - * - * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }) - * // => { 'a': 1, 'b': 2 } - */ -function defaults(obj, ...sources) { - obj = Object(obj); - sources.forEach(source => { - if (source != null) { - source = Object(source); - for (const key in source) { // tslint:disable-line - const value = obj[key]; - if (value === undefined || - (value === objectProto[key] && !hasOwnProperty.call(obj, key))) { - obj[key] = source[key]; - } - } - } - }); - return obj; -} -exports.defaults = defaults; -function omit(obj, properties) { - let o = {}; - for (let key of Object.keys(obj)) { - if (properties.indexOf(key) == -1) { - o[key] = obj[key]; - } - } - return o; -} -exports.omit = omit; -//# sourceMappingURL=lodash.js.map -/***/ }), -/* 316 */ -/***/ (function(module, exports) { +// tar -x +const hlo = __webpack_require__(280) +const Unpack = __webpack_require__(306) +const fs = __webpack_require__(4) +const fsm = __webpack_require__(300) +const path = __webpack_require__(20) -module.exports = require("module"); +const x = module.exports = (opt_, files, cb) => { + if (typeof opt_ === 'function') + cb = opt_, files = null, opt_ = {} + else if (Array.isArray(opt_)) + files = opt_, opt_ = {} -/***/ }), -/* 317 */ -/***/ (function(module, exports, __webpack_require__) { + if (typeof files === 'function') + cb = files, files = null -"use strict"; + if (!files) + files = [] + else + files = Array.from(files) + + const opt = hlo(opt_) + + if (opt.sync && typeof cb === 'function') + throw new TypeError('callback not supported for sync tar functions') + + if (!opt.file && typeof cb === 'function') + throw new TypeError('callback only supported with file option') + + if (files.length) + filesFilter(opt, files) + + return opt.file && opt.sync ? extractFileSync(opt) + : opt.file ? extractFile(opt, cb) + : opt.sync ? extractSync(opt) + : extract(opt) +} + +// construct a filter that limits the file entries listed +// include child entries if a dir is included +const filesFilter = (opt, files) => { + const map = new Map(files.map(f => [f.replace(/\/+$/, ''), true])) + const filter = opt.filter + + const mapHas = (file, r) => { + const root = r || path.parse(file).root || '.' + const ret = file === root ? false + : map.has(file) ? map.get(file) + : mapHas(path.dirname(file), root) + + map.set(file, ret) + return ret + } + + opt.filter = filter + ? (file, entry) => filter(file, entry) && mapHas(file.replace(/\/+$/, '')) + : file => mapHas(file.replace(/\/+$/, '')) +} + +const extractFileSync = opt => { + const u = new Unpack.Sync(opt) + + const file = opt.file + let threw = true + let fd + const stat = fs.statSync(file) + // This trades a zero-byte read() syscall for a stat + // However, it will usually result in less memory allocation + const readSize = opt.maxReadSize || 16*1024*1024 + const stream = new fsm.ReadStreamSync(file, { + readSize: readSize, + size: stat.size + }) + stream.pipe(u) +} + +const extractFile = (opt, cb) => { + const u = new Unpack(opt) + const readSize = opt.maxReadSize || 16*1024*1024 + + const file = opt.file + const p = new Promise((resolve, reject) => { + u.on('error', reject) + u.on('close', resolve) + + // This trades a zero-byte read() syscall for a stat + // However, it will usually result in less memory allocation + fs.stat(file, (er, stat) => { + if (er) + reject(er) + else { + const stream = new fsm.ReadStream(file, { + readSize: readSize, + size: stat.size + }) + stream.on('error', reject) + stream.pipe(u) + } + }) + }) + return cb ? p.then(cb, cb) : p +} + +const extractSync = opt => { + return new Unpack.Sync(opt) +} + +const extract = opt => { + return new Unpack(opt) +} -Object.defineProperty(exports, "__esModule", { value: true }); -const tslib_1 = __webpack_require__(3); -const commands_1 = tslib_1.__importDefault(__webpack_require__(247)); -exports.commands = commands_1.default; -const events_1 = tslib_1.__importDefault(__webpack_require__(149)); -exports.events = events_1.default; -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); -exports.languages = languages_1.default; -const document_1 = tslib_1.__importDefault(__webpack_require__(210)); -exports.Document = document_1.default; -const mru_1 = tslib_1.__importDefault(__webpack_require__(218)); -exports.Mru = mru_1.default; -const floatBuffer_1 = tslib_1.__importDefault(__webpack_require__(321)); -exports.FloatBuffer = floatBuffer_1.default; -const floatFactory_1 = tslib_1.__importDefault(__webpack_require__(320)); -exports.FloatFactory = floatFactory_1.default; -const fetch_1 = tslib_1.__importDefault(__webpack_require__(307)); -exports.fetch = fetch_1.default; -const download_1 = tslib_1.__importDefault(__webpack_require__(268)); -exports.download = download_1.default; -const highligher_1 = tslib_1.__importDefault(__webpack_require__(352)); -exports.Highligher = highligher_1.default; -const fileSystemWatcher_1 = tslib_1.__importDefault(__webpack_require__(217)); -exports.FileSystemWatcher = fileSystemWatcher_1.default; -const services_1 = tslib_1.__importDefault(__webpack_require__(354)); -exports.services = services_1.default; -const sources_1 = tslib_1.__importDefault(__webpack_require__(252)); -exports.sources = sources_1.default; -const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -exports.workspace = workspace_1.default; -const extensions_1 = tslib_1.__importDefault(__webpack_require__(253)); -exports.extensions = extensions_1.default; -const manager_1 = tslib_1.__importDefault(__webpack_require__(370)); -exports.listManager = manager_1.default; -const manager_2 = tslib_1.__importDefault(__webpack_require__(248)); -exports.snippetManager = manager_2.default; -const basic_1 = tslib_1.__importDefault(__webpack_require__(377)); -exports.BasicList = basic_1.default; -const manager_3 = tslib_1.__importDefault(__webpack_require__(319)); -exports.diagnosticManager = manager_3.default; -const ansiparse_1 = __webpack_require__(353); -exports.ansiparse = ansiparse_1.ansiparse; -const watchman_1 = tslib_1.__importDefault(__webpack_require__(230)); -exports.Watchman = watchman_1.default; -const vscode_uri_1 = __webpack_require__(183); -exports.Uri = vscode_uri_1.URI; -const neovim_1 = __webpack_require__(94); -exports.Neovim = neovim_1.Neovim; -exports.Buffer = neovim_1.Buffer; -exports.Window = neovim_1.Window; -const vscode_languageserver_protocol_1 = __webpack_require__(150); -exports.Disposable = vscode_languageserver_protocol_1.Disposable; -exports.Event = vscode_languageserver_protocol_1.Event; -exports.Emitter = vscode_languageserver_protocol_1.Emitter; -tslib_1.__exportStar(__webpack_require__(192), exports); -tslib_1.__exportStar(__webpack_require__(355), exports); -var util_1 = __webpack_require__(177); -exports.disposeAll = util_1.disposeAll; -exports.runCommand = util_1.runCommand; -exports.isRunning = util_1.isRunning; -exports.executable = util_1.executable; -//# sourceMappingURL=index.js.map /***/ }), -/* 318 */ +/* 306 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const tslib_1 = __webpack_require__(3); -const vscode_languageserver_protocol_1 = __webpack_require__(150); -const commands_1 = tslib_1.__importDefault(__webpack_require__(247)); -const manager_1 = tslib_1.__importDefault(__webpack_require__(319)); -const codeActionmanager_1 = tslib_1.__importDefault(__webpack_require__(330)); -const codeLensManager_1 = tslib_1.__importDefault(__webpack_require__(332)); -const declarationManager_1 = tslib_1.__importDefault(__webpack_require__(333)); -const definitionManager_1 = tslib_1.__importDefault(__webpack_require__(334)); -const documentColorManager_1 = tslib_1.__importDefault(__webpack_require__(335)); -const documentHighlightManager_1 = tslib_1.__importDefault(__webpack_require__(336)); -const documentLinkManager_1 = tslib_1.__importDefault(__webpack_require__(337)); -const documentSymbolManager_1 = tslib_1.__importDefault(__webpack_require__(338)); -const foldingRangeManager_1 = tslib_1.__importDefault(__webpack_require__(339)); -const formatManager_1 = tslib_1.__importDefault(__webpack_require__(340)); -const formatRangeManager_1 = tslib_1.__importDefault(__webpack_require__(341)); -const hoverManager_1 = tslib_1.__importDefault(__webpack_require__(342)); -const implementationManager_1 = tslib_1.__importDefault(__webpack_require__(343)); -const onTypeFormatManager_1 = tslib_1.__importDefault(__webpack_require__(344)); -const rangeManager_1 = tslib_1.__importDefault(__webpack_require__(345)); -const referenceManager_1 = tslib_1.__importDefault(__webpack_require__(346)); -const renameManager_1 = tslib_1.__importDefault(__webpack_require__(347)); -const signatureManager_1 = tslib_1.__importDefault(__webpack_require__(348)); -const typeDefinitionManager_1 = tslib_1.__importDefault(__webpack_require__(349)); -const workspaceSymbolsManager_1 = tslib_1.__importDefault(__webpack_require__(350)); -const manager_2 = tslib_1.__importDefault(__webpack_require__(248)); -const sources_1 = tslib_1.__importDefault(__webpack_require__(252)); -const types_1 = __webpack_require__(192); -const util_1 = __webpack_require__(177); -const complete = tslib_1.__importStar(__webpack_require__(351)); -const position_1 = __webpack_require__(216); -const string_1 = __webpack_require__(213); -const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const logger = __webpack_require__(2)('languages'); -function fixDocumentation(str) { - return str.replace(/ /g, ' '); -} -function check(_target, key, descriptor) { - let fn = descriptor.value; - if (typeof fn !== 'function') { - return; - } - descriptor.value = function (...args) { - let { cancelTokenSource } = this; - this.cancelTokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource(); - return new Promise((resolve, reject) => { - let resolved = false; - let timer = setTimeout(() => { - cancelTokenSource.cancel(); - logger.error(`${key} timeout after 5s`); - if (!resolved) - reject(new Error(`${key} timeout after 5s`)); - }, 5000); - Promise.resolve(fn.apply(this, args)).then(res => { - clearTimeout(timer); - resolve(res); - }, e => { - clearTimeout(timer); - reject(e); - }); - }); - }; -} -exports.check = check; -class Languages { - constructor() { - this.onTypeFormatManager = new onTypeFormatManager_1.default(); - this.documentLinkManager = new documentLinkManager_1.default(); - this.documentColorManager = new documentColorManager_1.default(); - this.foldingRangeManager = new foldingRangeManager_1.default(); - this.renameManager = new renameManager_1.default(); - this.formatManager = new formatManager_1.default(); - this.codeActionManager = new codeActionmanager_1.default(); - this.workspaceSymbolsManager = new workspaceSymbolsManager_1.default(); - this.formatRangeManager = new formatRangeManager_1.default(); - this.hoverManager = new hoverManager_1.default(); - this.signatureManager = new signatureManager_1.default(); - this.documentSymbolManager = new documentSymbolManager_1.default(); - this.documentHighlightManager = new documentHighlightManager_1.default(); - this.definitionManager = new definitionManager_1.default(); - this.declarationManager = new declarationManager_1.default(); - this.typeDefinitionManager = new typeDefinitionManager_1.default(); - this.referenceManager = new referenceManager_1.default(); - this.implementationManager = new implementationManager_1.default(); - this.codeLensManager = new codeLensManager_1.default(); - this.selectionRangeManager = new rangeManager_1.default(); - this.cancelTokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource(); - workspace_1.default.onWillSaveUntil(event => { - let { languageId } = event.document; - let config = workspace_1.default.getConfiguration('coc.preferences', event.document.uri); - let filetypes = config.get('formatOnSaveFiletypes', []); - if (filetypes.indexOf(languageId) !== -1 || filetypes.some(item => item === '*')) { - let willSaveWaitUntil = async () => { - let options = await workspace_1.default.getFormatOptions(event.document.uri); - let textEdits = await this.provideDocumentFormattingEdits(event.document, options); - return textEdits; - }; - event.waitUntil(willSaveWaitUntil()); - } - }, null, 'languageserver'); - workspace_1.default.ready.then(() => { - this.loadCompleteConfig(); - }, _e => { - // noop - }); - workspace_1.default.onDidChangeConfiguration(this.loadCompleteConfig, this); - } - get nvim() { - return workspace_1.default.nvim; - } - loadCompleteConfig() { - let config = workspace_1.default.getConfiguration('coc.preferences'); - let suggest = workspace_1.default.getConfiguration('suggest'); - function getConfig(key, defaultValue) { - return config.get(key, suggest.get(key, defaultValue)); - } - let labels = suggest.get('completionItemKindLabels', {}); - this.completionItemKindMap = new Map([ - [vscode_languageserver_protocol_1.CompletionItemKind.Text, labels['text'] || 'v'], - [vscode_languageserver_protocol_1.CompletionItemKind.Method, labels['method'] || 'f'], - [vscode_languageserver_protocol_1.CompletionItemKind.Function, labels['function'] || 'f'], - [vscode_languageserver_protocol_1.CompletionItemKind.Constructor, typeof labels['constructor'] == 'function' ? 'f' : labels['con' + 'structor']], - [vscode_languageserver_protocol_1.CompletionItemKind.Field, labels['field'] || 'm'], - [vscode_languageserver_protocol_1.CompletionItemKind.Variable, labels['variable'] || 'v'], - [vscode_languageserver_protocol_1.CompletionItemKind.Class, labels['class'] || 'C'], - [vscode_languageserver_protocol_1.CompletionItemKind.Interface, labels['interface'] || 'I'], - [vscode_languageserver_protocol_1.CompletionItemKind.Module, labels['module'] || 'M'], - [vscode_languageserver_protocol_1.CompletionItemKind.Property, labels['property'] || 'm'], - [vscode_languageserver_protocol_1.CompletionItemKind.Unit, labels['unit'] || 'U'], - [vscode_languageserver_protocol_1.CompletionItemKind.Value, labels['value'] || 'v'], - [vscode_languageserver_protocol_1.CompletionItemKind.Enum, labels['enum'] || 'E'], - [vscode_languageserver_protocol_1.CompletionItemKind.Keyword, labels['keyword'] || 'k'], - [vscode_languageserver_protocol_1.CompletionItemKind.Snippet, labels['snippet'] || 'S'], - [vscode_languageserver_protocol_1.CompletionItemKind.Color, labels['color'] || 'v'], - [vscode_languageserver_protocol_1.CompletionItemKind.File, labels['file'] || 'F'], - [vscode_languageserver_protocol_1.CompletionItemKind.Reference, labels['reference'] || 'r'], - [vscode_languageserver_protocol_1.CompletionItemKind.Folder, labels['folder'] || 'F'], - [vscode_languageserver_protocol_1.CompletionItemKind.EnumMember, labels['enumMember'] || 'm'], - [vscode_languageserver_protocol_1.CompletionItemKind.Constant, labels['constant'] || 'v'], - [vscode_languageserver_protocol_1.CompletionItemKind.Struct, labels['struct'] || 'S'], - [vscode_languageserver_protocol_1.CompletionItemKind.Event, labels['event'] || 'E'], - [vscode_languageserver_protocol_1.CompletionItemKind.Operator, labels['operator'] || 'O'], - [vscode_languageserver_protocol_1.CompletionItemKind.TypeParameter, labels['typeParameter'] || 'T'], - ]); - this.completeConfig = { - defaultKindText: labels['default'] || '', - priority: getConfig('languageSourcePriority', 99), - echodocSupport: getConfig('echodocSupport', false), - waitTime: getConfig('triggerCompletionWait', 60), - detailField: getConfig('detailField', 'abbr'), - detailMaxLength: getConfig('detailMaxLength', 50), - invalidInsertCharacters: getConfig('invalidInsertCharacters', [' ', '(', '<', '{', '[', '\r', '\n']), - }; - } - registerOnTypeFormattingEditProvider(selector, provider, triggerCharacters) { - return this.onTypeFormatManager.register(selector, provider, triggerCharacters); - } - registerCompletionItemProvider(name, shortcut, languageIds, provider, triggerCharacters = [], allCommitCharacters = [], priority) { - languageIds = typeof languageIds == 'string' ? [languageIds] : languageIds; - let source = this.createCompleteSource(name, shortcut, provider, languageIds, triggerCharacters, allCommitCharacters, priority); - sources_1.default.addSource(source); - logger.debug('created service source', name); - return { - dispose: () => { - sources_1.default.removeSource(source); - } - }; - } - registerCodeActionProvider(selector, provider, clientId, codeActionKinds) { - return this.codeActionManager.register(selector, provider, clientId, codeActionKinds); - } - registerHoverProvider(selector, provider) { - return this.hoverManager.register(selector, provider); - } - registerSelectionRangeProvider(selector, provider) { - return this.selectionRangeManager.register(selector, provider); - } - registerSignatureHelpProvider(selector, provider, triggerCharacters) { - return this.signatureManager.register(selector, provider, triggerCharacters); - } - registerDocumentSymbolProvider(selector, provider) { - return this.documentSymbolManager.register(selector, provider); - } - registerFoldingRangeProvider(selector, provider) { - return this.foldingRangeManager.register(selector, provider); - } - registerDocumentHighlightProvider(selector, provider) { - return this.documentHighlightManager.register(selector, provider); - } - registerCodeLensProvider(selector, provider) { - return this.codeLensManager.register(selector, provider); - } - registerDocumentLinkProvider(selector, provider) { - return this.documentLinkManager.register(selector, provider); - } - registerDocumentColorProvider(selector, provider) { - return this.documentColorManager.register(selector, provider); - } - registerDefinitionProvider(selector, provider) { - return this.definitionManager.register(selector, provider); - } - registerDeclarationProvider(selector, provider) { - return this.declarationManager.register(selector, provider); - } - registerTypeDefinitionProvider(selector, provider) { - return this.typeDefinitionManager.register(selector, provider); - } - registerImplementationProvider(selector, provider) { - return this.implementationManager.register(selector, provider); - } - registerReferencesProvider(selector, provider) { - return this.referenceManager.register(selector, provider); - } - registerRenameProvider(selector, provider) { - return this.renameManager.register(selector, provider); - } - registerWorkspaceSymbolProvider(selector, provider) { - return this.workspaceSymbolsManager.register(selector, provider); - } - registerDocumentFormatProvider(selector, provider, priority = 0) { - return this.formatManager.register(selector, provider, priority); - } - registerDocumentRangeFormatProvider(selector, provider, priority = 0) { - return this.formatRangeManager.register(selector, provider, priority); - } - shouldTriggerSignatureHelp(document, triggerCharacter) { - return this.signatureManager.shouldTrigger(document, triggerCharacter); - } - async getHover(document, position) { - return await this.hoverManager.provideHover(document, position, this.token); - } - async getSignatureHelp(document, position, token) { - return await this.signatureManager.provideSignatureHelp(document, position, token); - } - async getDefinition(document, position) { - if (!this.definitionManager.hasProvider(document)) - return null; - return await this.definitionManager.provideDefinition(document, position, this.token); - } - async getDeclaration(document, position) { - if (!this.declarationManager.hasProvider(document)) - return null; - return await this.declarationManager.provideDeclaration(document, position, this.token); - } - async getTypeDefinition(document, position) { - if (!this.typeDefinitionManager.hasProvider(document)) - return null; - return await this.typeDefinitionManager.provideTypeDefinition(document, position, this.token); - } - async getImplementation(document, position) { - if (!this.implementationManager.hasProvider(document)) - return null; - return await this.implementationManager.provideReferences(document, position, this.token); - } - async getReferences(document, context, position) { - if (!this.referenceManager.hasProvider(document)) - return null; - return await this.referenceManager.provideReferences(document, position, context, this.token); - } - async getDocumentSymbol(document) { - return await this.documentSymbolManager.provideDocumentSymbols(document, this.token); - } - async getSelectionRanges(document, positions) { - return await this.selectionRangeManager.provideSelectionRanges(document, positions, this.token); - } - async getWorkspaceSymbols(document, query) { - query = query || ''; - return await this.workspaceSymbolsManager.provideWorkspaceSymbols(document, query, this.token); - } - async resolveWorkspaceSymbol(symbol) { - return await this.workspaceSymbolsManager.resolveWorkspaceSymbol(symbol, this.token); - } - async provideRenameEdits(document, position, newName) { - return await this.renameManager.provideRenameEdits(document, position, newName, this.token); - } - async prepareRename(document, position) { - return await this.renameManager.prepareRename(document, position, this.token); - } - async provideDocumentFormattingEdits(document, options) { - if (!this.formatManager.hasProvider(document)) { - let hasRangeFormater = this.formatRangeManager.hasProvider(document); - if (!hasRangeFormater) { - logger.error('Format provider not found for current document', 'error'); - return null; - } - let end = document.positionAt(document.getText().length); - let range = vscode_languageserver_protocol_1.Range.create(vscode_languageserver_protocol_1.Position.create(0, 0), end); - return await this.provideDocumentRangeFormattingEdits(document, range, options); - } - return await this.formatManager.provideDocumentFormattingEdits(document, options, this.token); - } - async provideDocumentRangeFormattingEdits(document, range, options) { - if (!this.formatRangeManager.hasProvider(document)) - return null; - return await this.formatRangeManager.provideDocumentRangeFormattingEdits(document, range, options, this.token); - } - /** - * Get CodeAction list for current document - * - * @public - * @param {TextDocument} document - * @param {Range} range - * @param {CodeActionContext} context - * @returns {Promise} - */ - async getCodeActions(document, range, context, silent = false) { - if (!silent && !this.codeActionManager.hasProvider(document)) { - return null; - } - return await this.codeActionManager.provideCodeActions(document, range, context, this.token); - } - async getDocumentHighLight(document, position) { - return await this.documentHighlightManager.provideDocumentHighlights(document, position, this.token); - } - async getDocumentLinks(document) { - if (!this.documentLinkManager.hasProvider(document)) { - return null; - } - return (await this.documentLinkManager.provideDocumentLinks(document, this.token)) || []; - } - async resolveDocumentLink(link) { - return await this.documentLinkManager.resolveDocumentLink(link, this.token); - } - async provideDocumentColors(document) { - return await this.documentColorManager.provideDocumentColors(document, this.token); - } - async provideFoldingRanges(document, context) { - if (!this.formatRangeManager.hasProvider(document)) { - return null; - } - return await this.foldingRangeManager.provideFoldingRanges(document, context, this.token); - } - async provideColorPresentations(color, document) { - return await this.documentColorManager.provideColorPresentations(color, document, this.token); - } - async getCodeLens(document) { - return await this.codeLensManager.provideCodeLenses(document, this.token); - } - async resolveCodeLens(codeLens) { - return await this.codeLensManager.resolveCodeLens(codeLens, this.token); - } - async provideDocumentOnTypeEdits(character, document, position) { - return this.onTypeFormatManager.onCharacterType(character, document, position, this.token); - } - hasOnTypeProvider(character, document) { - return this.onTypeFormatManager.getProvider(document, character) != null; - } - hasProvider(id, document) { - switch (id) { - case 'rename': - return this.renameManager.hasProvider(document); - case 'onTypeEdit': - return this.onTypeFormatManager.hasProvider(document); - case 'documentLink': - return this.documentLinkManager.hasProvider(document); - case 'documentColor': - return this.documentColorManager.hasProvider(document); - case 'foldingRange': - return this.foldingRangeManager.hasProvider(document); - case 'format': - return this.formatManager.hasProvider(document); - case 'codeAction': - return this.codeActionManager.hasProvider(document); - case 'workspaceSymbols': - return this.workspaceSymbolsManager.hasProvider(document); - case 'formatRange': - return this.formatRangeManager.hasProvider(document); - case 'hover': - return this.hoverManager.hasProvider(document); - case 'signature': - return this.signatureManager.hasProvider(document); - case 'documentSymbol': - return this.documentSymbolManager.hasProvider(document); - case 'documentHighlight': - return this.documentHighlightManager.hasProvider(document); - case 'definition': - return this.definitionManager.hasProvider(document); - case 'declaration': - return this.declarationManager.hasProvider(document); - case 'typeDefinition': - return this.typeDefinitionManager.hasProvider(document); - case 'reference': - return this.referenceManager.hasProvider(document); - case 'implementation': - return this.implementationManager.hasProvider(document); - case 'codeLens': - return this.codeLensManager.hasProvider(document); - case 'selectionRange': - return this.selectionRangeManager.hasProvider(document); - default: - throw new Error(`${id} not supported.`); - } - } - dispose() { - // noop - } - createDiagnosticCollection(owner) { - return manager_1.default.create(owner); - } - createCompleteSource(name, shortcut, provider, languageIds, triggerCharacters, allCommitCharacters, priority) { - // track them for resolve - let completeItems = []; - // line used for TextEdit - let hasResolve = typeof provider.resolveCompletionItem === 'function'; - priority = priority == null ? this.completeConfig.priority : priority; - // index set of resolved items - let resolvedIndexes = new Set(); - let waitTime = Math.min(Math.max(50, this.completeConfig.waitTime), 300); - let source = { - name, - priority, - shortcut, - enable: true, - sourceType: types_1.SourceType.Service, - filetypes: languageIds, - triggerCharacters: triggerCharacters || [], - doComplete: async (opt, token) => { - let { triggerCharacter, bufnr } = opt; - resolvedIndexes = new Set(); - let isTrigger = triggerCharacters && triggerCharacters.indexOf(triggerCharacter) != -1; - let triggerKind = vscode_languageserver_protocol_1.CompletionTriggerKind.Invoked; - if (opt.triggerForInComplete) { - triggerKind = vscode_languageserver_protocol_1.CompletionTriggerKind.TriggerForIncompleteCompletions; - } - else if (isTrigger) { - triggerKind = vscode_languageserver_protocol_1.CompletionTriggerKind.TriggerCharacter; - } - if (opt.triggerCharacter) - await util_1.wait(waitTime); - if (token.isCancellationRequested) - return null; - let position = complete.getPosition(opt); - let context = { triggerKind, option: opt }; - if (isTrigger) - context.triggerCharacter = triggerCharacter; - let result; - try { - let doc = workspace_1.default.getDocument(bufnr); - result = await Promise.resolve(provider.provideCompletionItems(doc.textDocument, position, token, context)); - } - catch (e) { - // don't disturb user - logger.error(`Source "${name}" complete error:`, e); - return null; - } - if (!result || token.isCancellationRequested) - return null; - completeItems = Array.isArray(result) ? result : result.items; - if (!completeItems || completeItems.length == 0) - return null; - // used for fixed col - let option = Object.assign({}, opt); - if (typeof result.startcol == 'number') { - option.col = result.startcol; - } - let items = completeItems.map((o, index) => { - let item = this.convertVimCompleteItem(o, shortcut, option); - item.index = index; - return item; - }); - return { - startcol: result.startcol, - isIncomplete: !!result.isIncomplete, - items - }; - }, - onCompleteResolve: async (item, token) => { - let resolving = completeItems[item.index]; - if (!resolving) - return; - if (hasResolve && !resolvedIndexes.has(item.index)) { - let resolved = await Promise.resolve(provider.resolveCompletionItem(resolving, token)); - if (token.isCancellationRequested) - return; - resolvedIndexes.add(item.index); - if (resolved) - Object.assign(resolving, resolved); - } - if (item.documentation == null) { - let { documentation, detail } = resolving; - if (!documentation && !detail) - return; - let docs = []; - if (detail && !item.detailShown && detail != item.word) { - detail = detail.replace(/\n\s*/g, ' '); - if (detail.length) { - let isText = /^[\w-\s.,\t]+$/.test(detail); - let filetype = isText ? 'txt' : await workspace_1.default.nvim.eval('&filetype'); - docs.push({ filetype: isText ? 'txt' : filetype, content: detail }); - } - } - if (documentation) { - if (typeof documentation == 'string') { - docs.push({ - filetype: 'markdown', - content: fixDocumentation(documentation) - }); - } - else if (documentation.value) { - docs.push({ - filetype: documentation.kind == 'markdown' ? 'markdown' : 'txt', - content: fixDocumentation(documentation.value) - }); - } - } - item.documentation = docs; - } - }, - onCompleteDone: async (vimItem, opt) => { - let item = completeItems[vimItem.index]; - if (!item) - return; - let line = opt.linenr - 1; - // tslint:disable-next-line: deprecation - if (item.insertText && !item.textEdit) { - item.textEdit = { - range: vscode_languageserver_protocol_1.Range.create(line, opt.col, line, opt.colnr - 1), - // tslint:disable-next-line: deprecation - newText: item.insertText - }; - } - if (vimItem.line) - Object.assign(opt, { line: vimItem.line }); - try { - let isSnippet = await this.applyTextEdit(item, opt); - if (isSnippet && manager_2.default.isPlainText(item.textEdit.newText)) { - isSnippet = false; - } - let { additionalTextEdits } = item; - if (additionalTextEdits && item.textEdit) { - let r = item.textEdit.range; - additionalTextEdits = additionalTextEdits.filter(edit => { - if (position_1.rangeOverlap(r, edit.range)) { - logger.error('Filtered overlap additionalTextEdit:', edit); - return false; - } - return true; - }); - } - await this.applyAdditionalEdits(additionalTextEdits, opt.bufnr, isSnippet); - if (isSnippet) - await manager_2.default.selectCurrentPlaceholder(); - if (item.command) - commands_1.default.execute(item.command); - } - catch (e) { - logger.error('Error on CompleteDone:', e); - } - }, - shouldCommit: (item, character) => { - let completeItem = completeItems[item.index]; - if (!completeItem) - return false; - let commitCharacters = completeItem.commitCharacters || allCommitCharacters; - return commitCharacters.indexOf(character) !== -1; - } - }; - return source; - } - get token() { - this.cancelTokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource(); - return this.cancelTokenSource.token; - } - async applyTextEdit(item, option) { - let { nvim } = this; - let { textEdit } = item; - if (!textEdit) - return false; - let { line, bufnr, linenr } = option; - let doc = workspace_1.default.getDocument(bufnr); - if (!doc) - return false; - let { range, newText } = textEdit; - let isSnippet = item.insertTextFormat === vscode_languageserver_protocol_1.InsertTextFormat.Snippet; - // replace inserted word - let start = line.substr(0, range.start.character); - let end = line.substr(range.end.character); - if (isSnippet) { - await doc.applyEdits(nvim, [{ - range: vscode_languageserver_protocol_1.Range.create(linenr - 1, 0, linenr, 0), - newText: `${start}${end}\n` - }]); - // can't select, since additionalTextEdits would break selection - let pos = vscode_languageserver_protocol_1.Position.create(linenr - 1, range.start.character); - return await manager_2.default.insertSnippet(newText, false, vscode_languageserver_protocol_1.Range.create(pos, pos)); - } - let newLines = `${start}${newText}${end}`.split('\n'); - if (newLines.length == 1) { - await nvim.call('coc#util#setline', [linenr, newLines[0]]); - await workspace_1.default.moveTo(vscode_languageserver_protocol_1.Position.create(linenr - 1, (start + newText).length)); - } - else { - let buffer = nvim.createBuffer(bufnr); - await buffer.setLines(newLines, { - start: linenr - 1, - end: linenr, - strictIndexing: false - }); - let line = linenr - 1 + newLines.length - 1; - let character = newLines[newLines.length - 1].length - end.length; - await workspace_1.default.moveTo({ line, character }); - } - return false; - } - async applyAdditionalEdits(textEdits, bufnr, snippet) { - if (!textEdits || textEdits.length == 0) - return; - let document = workspace_1.default.getDocument(bufnr); - if (!document) - return; - await document._fetchContent(); - // how to move cursor after edit - let changed = null; - let pos = await workspace_1.default.getCursorPosition(); - if (!snippet) - changed = position_1.getChangedFromEdits(pos, textEdits); - await document.applyEdits(this.nvim, textEdits); - if (changed) - await workspace_1.default.moveTo(vscode_languageserver_protocol_1.Position.create(pos.line + changed.line, pos.character + changed.character)); - } - convertVimCompleteItem(item, shortcut, opt) { - let { echodocSupport, detailField, detailMaxLength, invalidInsertCharacters } = this.completeConfig; - let hasAdditionalEdit = item.additionalTextEdits && item.additionalTextEdits.length > 0; - let isSnippet = item.insertTextFormat === vscode_languageserver_protocol_1.InsertTextFormat.Snippet || hasAdditionalEdit; - let label = item.label.trim(); - let obj = { - word: complete.getWord(item, opt, invalidInsertCharacters), - abbr: label, - menu: `[${shortcut}]`, - kind: complete.completionKindString(item.kind, this.completionItemKindMap, this.completeConfig.defaultKindText), - sortText: item.sortText || null, - sourceScore: item['score'] || null, - filterText: item.filterText || label, - isSnippet, - dup: item.data && item.data.dup == 0 ? 0 : 1 - }; - if (item && item.detail && detailField != 'preview') { - let detail = item.detail.replace(/\n\s*/g, ' '); - if (string_1.byteLength(detail) < detailMaxLength) { - if (detailField == 'menu') { - obj.menu = `${detail} ${obj.menu}`; - } - else if (detailField == 'abbr') { - obj.abbr = `${obj.abbr} - ${detail}`; - } - obj.detailShown = 1; - } - } - if (item.documentation) { - obj.info = typeof item.documentation == 'string' ? item.documentation : item.documentation.value; - } - else { - obj.info = ''; - } - if (!obj.word) - obj.empty = 1; - if (item.textEdit) - obj.line = opt.line; - if (item.kind == vscode_languageserver_protocol_1.CompletionItemKind.Folder && !obj.abbr.endsWith('/')) { - obj.abbr = obj.abbr + '/'; - } - if (echodocSupport && item.kind >= 2 && item.kind <= 4) { - let fields = [item.detail || '', obj.abbr, obj.word]; - for (let s of fields) { - if (s.indexOf('(') !== -1) { - obj.signature = s; - break; - } - } - } - if (item.preselect) - obj.preselect = true; - item.data = item.data || {}; - if (item.data.optional) - obj.abbr = obj.abbr + '?'; - return obj; - } + +const assert = __webpack_require__(46) +const EE = __webpack_require__(137).EventEmitter +const Parser = __webpack_require__(302) +const fs = __webpack_require__(4) +const fsm = __webpack_require__(300) +const path = __webpack_require__(20) +const mkdir = __webpack_require__(307) +const mkdirSync = mkdir.sync +const wc = __webpack_require__(298) + +const ONENTRY = Symbol('onEntry') +const CHECKFS = Symbol('checkFs') +const ISREUSABLE = Symbol('isReusable') +const MAKEFS = Symbol('makeFs') +const FILE = Symbol('file') +const DIRECTORY = Symbol('directory') +const LINK = Symbol('link') +const SYMLINK = Symbol('symlink') +const HARDLINK = Symbol('hardlink') +const UNSUPPORTED = Symbol('unsupported') +const UNKNOWN = Symbol('unknown') +const CHECKPATH = Symbol('checkPath') +const MKDIR = Symbol('mkdir') +const ONERROR = Symbol('onError') +const PENDING = Symbol('pending') +const PEND = Symbol('pend') +const UNPEND = Symbol('unpend') +const ENDED = Symbol('ended') +const MAYBECLOSE = Symbol('maybeClose') +const SKIP = Symbol('skip') +const DOCHOWN = Symbol('doChown') +const UID = Symbol('uid') +const GID = Symbol('gid') +const crypto = __webpack_require__(160) + +// Unlinks on Windows are not atomic. +// +// This means that if you have a file entry, followed by another +// file entry with an identical name, and you cannot re-use the file +// (because it's a hardlink, or because unlink:true is set, or it's +// Windows, which does not have useful nlink values), then the unlink +// will be committed to the disk AFTER the new file has been written +// over the old one, deleting the new file. +// +// To work around this, on Windows systems, we rename the file and then +// delete the renamed file. It's a sloppy kludge, but frankly, I do not +// know of a better way to do this, given windows' non-atomic unlink +// semantics. +// +// See: https://github.com/npm/node-tar/issues/183 +/* istanbul ignore next */ +const unlinkFile = (path, cb) => { + if (process.platform !== 'win32') + return fs.unlink(path, cb) + + const name = path + '.DELETE.' + crypto.randomBytes(16).toString('hex') + fs.rename(path, name, er => { + if (er) + return cb(er) + fs.unlink(name, cb) + }) } -tslib_1.__decorate([ - check -], Languages.prototype, "getHover", null); -tslib_1.__decorate([ - check -], Languages.prototype, "getDefinition", null); -tslib_1.__decorate([ - check -], Languages.prototype, "getDeclaration", null); -tslib_1.__decorate([ - check -], Languages.prototype, "getTypeDefinition", null); -tslib_1.__decorate([ - check -], Languages.prototype, "getImplementation", null); -tslib_1.__decorate([ - check -], Languages.prototype, "getReferences", null); -tslib_1.__decorate([ - check -], Languages.prototype, "getDocumentSymbol", null); -tslib_1.__decorate([ - check -], Languages.prototype, "getSelectionRanges", null); -tslib_1.__decorate([ - check -], Languages.prototype, "getWorkspaceSymbols", null); -tslib_1.__decorate([ - check -], Languages.prototype, "resolveWorkspaceSymbol", null); -tslib_1.__decorate([ - check -], Languages.prototype, "provideRenameEdits", null); -tslib_1.__decorate([ - check -], Languages.prototype, "prepareRename", null); -tslib_1.__decorate([ - check -], Languages.prototype, "provideDocumentFormattingEdits", null); -tslib_1.__decorate([ - check -], Languages.prototype, "provideDocumentRangeFormattingEdits", null); -tslib_1.__decorate([ - check -], Languages.prototype, "getCodeActions", null); -tslib_1.__decorate([ - check -], Languages.prototype, "getDocumentHighLight", null); -tslib_1.__decorate([ - check -], Languages.prototype, "getDocumentLinks", null); -tslib_1.__decorate([ - check -], Languages.prototype, "resolveDocumentLink", null); -tslib_1.__decorate([ - check -], Languages.prototype, "provideDocumentColors", null); -tslib_1.__decorate([ - check -], Languages.prototype, "provideFoldingRanges", null); -tslib_1.__decorate([ - check -], Languages.prototype, "provideColorPresentations", null); -tslib_1.__decorate([ - check -], Languages.prototype, "getCodeLens", null); -tslib_1.__decorate([ - check -], Languages.prototype, "resolveCodeLens", null); -tslib_1.__decorate([ - check -], Languages.prototype, "provideDocumentOnTypeEdits", null); -exports.default = new Languages(); -//# sourceMappingURL=languages.js.map -/***/ }), -/* 319 */ -/***/ (function(module, exports, __webpack_require__) { +/* istanbul ignore next */ +const unlinkFileSync = path => { + if (process.platform !== 'win32') + return fs.unlinkSync(path) + + const name = path + '.DELETE.' + crypto.randomBytes(16).toString('hex') + fs.renameSync(path, name) + fs.unlinkSync(name) +} -"use strict"; +// this.gid, entry.gid, this.processUid +const uint32 = (a, b, c) => + a === a >>> 0 ? a + : b === b >>> 0 ? b + : c -Object.defineProperty(exports, "__esModule", { value: true }); -const tslib_1 = __webpack_require__(3); -const vscode_languageserver_protocol_1 = __webpack_require__(150); -const vscode_uri_1 = __webpack_require__(183); -const events_1 = tslib_1.__importDefault(__webpack_require__(149)); -const floatFactory_1 = tslib_1.__importDefault(__webpack_require__(320)); -const util_1 = __webpack_require__(177); -const position_1 = __webpack_require__(216); -const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const buffer_1 = __webpack_require__(326); -const collection_1 = tslib_1.__importDefault(__webpack_require__(329)); -const util_2 = __webpack_require__(328); -const logger = __webpack_require__(2)('diagnostic-manager'); -class DiagnosticManager { - constructor() { - this.enabled = true; - this.buffers = []; - this.lastMessage = ''; - this.collections = []; - this.disposables = []; - this.lastChanageTs = 0; - } - init() { - this.setConfiguration(); - let { nvim } = workspace_1.default; - let { maxWindowHeight, maxWindowWidth } = this.config; - this.floatFactory = new floatFactory_1.default(nvim, workspace_1.default.env, false, maxWindowHeight, maxWindowWidth); - this.disposables.push(vscode_languageserver_protocol_1.Disposable.create(() => { - if (this.timer) - clearTimeout(this.timer); - })); - events_1.default.on('CursorMoved', async () => { - if (this.timer) - clearTimeout(this.timer); - this.timer = setTimeout(async () => { - if (this.config.enableMessage != 'always') - return; - await this.echoMessage(true); - }, this.config.messageDelay); - }, null, this.disposables); - events_1.default.on('InsertEnter', async () => { - if (this.timer) - clearTimeout(this.timer); - this.floatFactory.close(); - }, null, this.disposables); - events_1.default.on('InsertLeave', async (bufnr) => { - this.floatFactory.close(); - let doc = workspace_1.default.getDocument(bufnr); - if (!doc || !this.shouldValidate(doc)) - return; - let { refreshOnInsertMode, refreshAfterSave } = this.config; - if (!refreshOnInsertMode && !refreshAfterSave) { - if (doc.dirty) { - doc.forceSync(); - await util_1.wait(50); - } - let d = 300 - (Date.now() - this.lastChanageTs); - if (d > 0) - await util_1.wait(d); - this.refreshBuffer(doc.uri); - } - }, null, this.disposables); - events_1.default.on('BufEnter', async () => { - if (this.timer) - clearTimeout(this.timer); - if (!this.enabled || !this.config.locationlist) - return; - let doc = await workspace_1.default.document; - if (!doc || doc.buftype == 'quickfix') - return; - if (this.shouldValidate(doc)) { - let refreshed = this.refreshBuffer(doc.uri); - if (refreshed) - return; - } - let curr = await nvim.eval(`getloclist(win_getid(),{'title':1})`); - if (curr.title && curr.title.indexOf('Diagnostics of coc') != -1) { - await nvim.eval(`setloclist(win_getid(),[],'f')`); - } - }, null, this.disposables); - events_1.default.on('BufWritePost', async (bufnr) => { - let buf = this.buffers.find(buf => buf.bufnr == bufnr); - if (buf) - await buf.checkSigns(); - await util_1.wait(100); - if (this.config.refreshAfterSave) { - this.refreshBuffer(buf.uri); - } - }, null, this.disposables); - events_1.default.on(['TextChanged', 'TextChangedI'], () => { - this.lastChanageTs = Date.now(); - }, null, this.disposables); - workspace_1.default.onDidChangeConfiguration(async (e) => { - this.setConfiguration(e); - }, null, this.disposables); - // create buffers - for (let doc of workspace_1.default.documents) { - this.createDiagnosticBuffer(doc); - } - workspace_1.default.onDidOpenTextDocument(textDocument => { - let doc = workspace_1.default.getDocument(textDocument.uri); - this.createDiagnosticBuffer(doc); - }, null, this.disposables); - workspace_1.default.onDidCloseTextDocument(({ uri }) => { - let doc = workspace_1.default.getDocument(uri); - if (!doc) - return; - this.disposeBuffer(doc.bufnr); - }, null, this.disposables); - this.setConfigurationErrors(true); - workspace_1.default.configurations.onError(async () => { - this.setConfigurationErrors(); - }, null, this.disposables); - let { errorSign, warningSign, infoSign, hintSign } = this.config; - nvim.pauseNotification(); - let signError = `sign define CocError linehl=CocErrorLine texthl=CocErrorSign`; - let signWarning = `sign define CocWarning linehl=CocWarningLine texthl=CocWarningSign`; - let signInfo = `sign define CocInfo linehl=CocInfoLine texthl=CocInfoSign`; - let signHint = `sign define CocHint linehl=CocHintLine texthl=CocHintSign`; - if (this.config.enableSign) { - signError += ` text=${errorSign}`; - signWarning += ` text=${warningSign}`; - signInfo += ` text=${infoSign}`; - signHint += ` text=${hintSign}`; - } - if (workspace_1.default.isNvim && this.config.enableHighlightLineNumber) { - signError += ' numhl=CocErrorSign'; - signWarning += ' numhl=CocWarningSign'; - signInfo += ' numhl=CocInfoSign'; - signHint += ' numhl=CocHintSign'; - } - nvim.command(signError, true); - nvim.command(signWarning, true); - nvim.command(signInfo, true); - nvim.command(signHint, true); - if (this.config.virtualText && workspace_1.default.isNvim) { - nvim.call('coc#util#init_virtual_hl', [], true); - } - nvim.resumeNotification(false, true).logError(); - } - createDiagnosticBuffer(doc) { - if (!this.shouldValidate(doc)) - return; - let idx = this.buffers.findIndex(b => b.bufnr == doc.bufnr); - if (idx == -1) { - let buf = new buffer_1.DiagnosticBuffer(doc.bufnr, this.config); - this.buffers.push(buf); - buf.onDidRefresh(() => { - if (workspace_1.default.insertMode) - return; - this.echoMessage(true).logError(); - }); - } - } - setConfigurationErrors(init) { - let collections = this.collections; - let collection = collections.find(o => o.name == 'config'); - if (!collection) { - collection = this.create('config'); - } - else { - collection.clear(); - } - let { errorItems } = workspace_1.default.configurations; - if (errorItems && errorItems.length) { - if (init) - workspace_1.default.showMessage(`settings file parse error, run ':CocList diagnostics'`, 'error'); - let entries = new Map(); - for (let item of errorItems) { - let { uri } = item.location; - let diagnostics = entries.get(uri) || []; - diagnostics.push(vscode_languageserver_protocol_1.Diagnostic.create(item.location.range, item.message, vscode_languageserver_protocol_1.DiagnosticSeverity.Error)); - entries.set(uri, diagnostics); - } - collection.set(Array.from(entries)); - } - } - /** - * Create collection by name - */ - create(name) { - let collection = new collection_1.default(name); - this.collections.push(collection); - // Used for refresh diagnostics on buferEnter when refreshAfterSave is true - // Note we can't make sure it work as expected when there're multiple sources - let createTime = Date.now(); - let refreshed = false; - collection.onDidDiagnosticsChange(async (uri) => { - if (this.config.refreshAfterSave && - (refreshed || Date.now() - createTime > 5000)) - return; - refreshed = true; - this.refreshBuffer(uri); - }); - collection.onDidDiagnosticsClear(uris => { - for (let uri of uris) { - this.refreshBuffer(uri); - } - }); - collection.onDispose(() => { - let idx = this.collections.findIndex(o => o == collection); - if (idx !== -1) - this.collections.splice(idx, 1); - }); - return collection; - } - /** - * Get diagnostics ranges from document - */ - getSortedRanges(uri, severity) { - let collections = this.getCollections(uri); - let res = []; - let level = severity ? util_2.severityLevel(severity) : 0; - for (let collection of collections) { - let diagnostics = collection.get(uri); - if (level) - diagnostics = diagnostics.filter(o => o.severity == level); - let ranges = diagnostics.map(o => o.range); - res.push(...ranges); - } - res.sort((a, b) => { - if (a.start.line != b.start.line) { - return a.start.line - b.start.line; - } - return a.start.character - b.start.character; - }); - return res; - } - /** - * Get readonly diagnostics for a buffer - */ - getDiagnostics(uri) { - let collections = this.getCollections(uri); - let { level } = this.config; - let res = []; - for (let collection of collections) { - let items = collection.get(uri); - if (!items) - continue; - if (level && level < vscode_languageserver_protocol_1.DiagnosticSeverity.Hint) { - items = items.filter(s => s.severity == null || s.severity <= level); - } - res.push(...items); - } - res.sort((a, b) => { - if (a.severity == b.severity) { - let d = position_1.comparePosition(a.range.start, b.range.start); - if (d != 0) - return d; - if (a.source == b.source) - return a.message > b.message ? 1 : -1; - return a.source > b.source ? 1 : -1; - } - return a.severity - b.severity; - }); - return res; +class Unpack extends Parser { + constructor (opt) { + if (!opt) + opt = {} + + opt.ondone = _ => { + this[ENDED] = true + this[MAYBECLOSE]() } - getDiagnosticsInRange(document, range) { - let collections = this.getCollections(document.uri); - let res = []; - for (let collection of collections) { - let items = collection.get(document.uri); - if (!items) - continue; - for (let item of items) { - if (position_1.rangeIntersect(item.range, range)) { - res.push(item); - } - } - } - return res; + + super(opt) + + this.transform = typeof opt.transform === 'function' ? opt.transform : null + + this.writable = true + this.readable = false + + this[PENDING] = 0 + this[ENDED] = false + + this.dirCache = opt.dirCache || new Map() + + if (typeof opt.uid === 'number' || typeof opt.gid === 'number') { + // need both or neither + if (typeof opt.uid !== 'number' || typeof opt.gid !== 'number') + throw new TypeError('cannot set owner without number uid and gid') + if (opt.preserveOwner) + throw new TypeError( + 'cannot preserve owner in archive and also set owner explicitly') + this.uid = opt.uid + this.gid = opt.gid + this.setOwner = true + } else { + this.uid = null + this.gid = null + this.setOwner = false } - /** - * Show diagnostics under curosr in preview window - */ - async preview() { - let [bufnr, cursor] = await this.nvim.eval('[bufnr("%"),coc#util#cursor()]'); - let { nvim } = this; - let diagnostics = await this.getDiagnosticsAt(bufnr, cursor); - if (diagnostics.length == 0) { - nvim.command('pclose', true); - workspace_1.default.showMessage(`Empty diagnostics`, 'warning'); - return; - } - let lines = []; - for (let diagnostic of diagnostics) { - let { source, code, severity, message } = diagnostic; - let s = util_2.getSeverityName(severity)[0]; - lines.push(`[${source}${code ? ' ' + code : ''}] [${s}]`); - lines.push(...message.split(/\r?\n/)); - lines.push(''); - } - lines = lines.slice(0, -1); - // let content = lines.join('\n').trim() - nvim.call('coc#util#preview_info', [lines, 'txt'], true); + + // default true for root + if (opt.preserveOwner === undefined && typeof opt.uid !== 'number') + this.preserveOwner = process.getuid && process.getuid() === 0 + else + this.preserveOwner = !!opt.preserveOwner + + this.processUid = (this.preserveOwner || this.setOwner) && process.getuid ? + process.getuid() : null + this.processGid = (this.preserveOwner || this.setOwner) && process.getgid ? + process.getgid() : null + + // mostly just for testing, but useful in some cases. + // Forcibly trigger a chown on every entry, no matter what + this.forceChown = opt.forceChown === true + + // turn > this[ONENTRY](entry)) + } + + [MAYBECLOSE] () { + if (this[ENDED] && this[PENDING] === 0) { + this.emit('prefinish') + this.emit('finish') + this.emit('end') + this.emit('close') } - /** - * Jump to previous diagnostic position - */ - async jumpPrevious(severity) { - let buffer = await this.nvim.buffer; - let document = workspace_1.default.getDocument(buffer.id); - if (!document) - return; - let offset = await workspace_1.default.getOffset(); - if (offset == null) - return; - let ranges = this.getSortedRanges(document.uri, severity); - if (ranges.length == 0) { - workspace_1.default.showMessage('Empty diagnostics', 'warning'); - return; - } - let { textDocument } = document; - for (let i = ranges.length - 1; i >= 0; i--) { - if (textDocument.offsetAt(ranges[i].end) < offset) { - await workspace_1.default.moveTo(ranges[i].start); - return; - } - } - if (await this.nvim.getOption('wrapscan')) { - await workspace_1.default.moveTo(ranges[ranges.length - 1].start); - } + } + + [CHECKPATH] (entry) { + if (this.strip) { + const parts = entry.path.split(/\/|\\/) + if (parts.length < this.strip) + return false + entry.path = parts.slice(this.strip).join('/') + + if (entry.type === 'Link') { + const linkparts = entry.linkpath.split(/\/|\\/) + if (linkparts.length >= this.strip) + entry.linkpath = linkparts.slice(this.strip).join('/') + } } - /** - * Jump to next diagnostic position - */ - async jumpNext(severity) { - let buffer = await this.nvim.buffer; - let document = workspace_1.default.getDocument(buffer.id); - let offset = await workspace_1.default.getOffset(); - let ranges = this.getSortedRanges(document.uri, severity); - if (ranges.length == 0) { - workspace_1.default.showMessage('Empty diagnostics', 'warning'); - return; - } - let { textDocument } = document; - for (let i = 0; i <= ranges.length - 1; i++) { - if (textDocument.offsetAt(ranges[i].start) > offset) { - await workspace_1.default.moveTo(ranges[i].start); - return; - } - } - if (await this.nvim.getOption('wrapscan')) { - await workspace_1.default.moveTo(ranges[0].start); - } + + if (!this.preservePaths) { + const p = entry.path + if (p.match(/(^|\/|\\)\.\.(\\|\/|$)/)) { + this.warn('path contains \'..\'', p) + return false + } + + // absolutes on posix are also absolutes on win32 + // so we only need to test this one to get both + if (path.win32.isAbsolute(p)) { + const parsed = path.win32.parse(p) + this.warn('stripping ' + parsed.root + ' from absolute path', p) + entry.path = p.substr(parsed.root.length) + } } - /** - * All diagnostics of current workspace - */ - getDiagnosticList() { - let res = []; - for (let collection of this.collections) { - collection.forEach((uri, diagnostics) => { - let file = vscode_uri_1.URI.parse(uri).fsPath; - for (let diagnostic of diagnostics) { - let { start } = diagnostic.range; - let o = { - file, - lnum: start.line + 1, - col: start.character + 1, - message: `[${diagnostic.source || collection.name}${diagnostic.code ? ' ' + diagnostic.code : ''}] ${diagnostic.message}`, - severity: util_2.getSeverityName(diagnostic.severity), - level: diagnostic.severity || 0, - location: vscode_languageserver_protocol_1.Location.create(uri, diagnostic.range) - }; - res.push(o); - } - }); - } - res.sort((a, b) => { - if (a.level !== b.level) { - return a.level - b.level; - } - if (a.file !== b.file) { - return a.file > b.file ? 1 : -1; - } - else { - if (a.lnum != b.lnum) { - return a.lnum - b.lnum; - } - return a.col - b.col; - } - }); - return res; + + // only encode : chars that aren't drive letter indicators + if (this.win32) { + const parsed = path.win32.parse(entry.path) + entry.path = parsed.root === '' ? wc.encode(entry.path) + : parsed.root + wc.encode(entry.path.substr(parsed.root.length)) } - async getDiagnosticsAt(bufnr, cursor) { - let pos = vscode_languageserver_protocol_1.Position.create(cursor[0], cursor[1]); - let buffer = this.buffers.find(o => o.bufnr == bufnr); - if (!buffer) - return []; - let { checkCurrentLine } = this.config; - let diagnostics = buffer.diagnostics.filter(o => position_1.positionInRange(pos, o.range) == 0); - if (diagnostics.length == 0 && checkCurrentLine) { - diagnostics = buffer.diagnostics.filter(o => position_1.lineInRange(pos.line, o.range)); - } - diagnostics.sort((a, b) => a.severity - b.severity); - return diagnostics; + + if (path.isAbsolute(entry.path)) + entry.absolute = entry.path + else + entry.absolute = path.resolve(this.cwd, entry.path) + + return true + } + + [ONENTRY] (entry) { + if (!this[CHECKPATH](entry)) + return entry.resume() + + assert.equal(typeof entry.absolute, 'string') + + switch (entry.type) { + case 'Directory': + case 'GNUDumpDir': + if (entry.mode) + entry.mode = entry.mode | 0o700 + + case 'File': + case 'OldFile': + case 'ContiguousFile': + case 'Link': + case 'SymbolicLink': + return this[CHECKFS](entry) + + case 'CharacterDevice': + case 'BlockDevice': + case 'FIFO': + return this[UNSUPPORTED](entry) } - async getCurrentDiagnostics() { - let [bufnr, cursor] = await this.nvim.eval('[bufnr("%"),coc#util#cursor()]'); - return await this.getDiagnosticsAt(bufnr, cursor); + } + + [ONERROR] (er, entry) { + // Cwd has to exist, or else nothing works. That's serious. + // Other errors are warnings, which raise the error in strict + // mode, but otherwise continue on. + if (er.name === 'CwdError') + this.emit('error', er) + else { + this.warn(er.message, er) + this[UNPEND]() + entry.resume() } - /** - * Echo diagnostic message of currrent position - */ - async echoMessage(truncate = false) { - const config = this.config; - if (!this.enabled || config.enableMessage == 'never') - return; - if (this.timer) - clearTimeout(this.timer); - let useFloat = config.messageTarget == 'float'; - let [bufnr, cursor] = await this.nvim.eval('[bufnr("%"),coc#util#cursor()]'); - if (useFloat) { - let { buffer } = this.floatFactory; - if (buffer && bufnr == buffer.id) - return; - } - let diagnostics = await this.getDiagnosticsAt(bufnr, cursor); - if (diagnostics.length == 0) { - if (useFloat) { - this.floatFactory.close(); - } - else { - let echoLine = await this.nvim.call('coc#util#echo_line'); - if (this.lastMessage && echoLine.startsWith(this.lastMessage)) { - this.nvim.command('echo ""', true); - } - } - return; - } - if (truncate && workspace_1.default.insertMode) - return; - let docs = []; - let ft = ''; - if (Object.keys(config.filetypeMap).length > 0) { - const filetype = await this.nvim.eval('&filetype'); - const defaultFiletype = config.filetypeMap['default'] || ''; - ft = config.filetypeMap[filetype] || (defaultFiletype == 'bufferType' ? filetype : defaultFiletype); - } - diagnostics.forEach(diagnostic => { - let { source, code, severity, message } = diagnostic; - let s = util_2.getSeverityName(severity)[0]; - const codeStr = code ? ' ' + code : ''; - const str = config.format.replace('%source', source).replace('%code', codeStr).replace('%severity', s).replace('%message', message); - let filetype = 'Error'; - if (ft === '') { - switch (severity) { - case vscode_languageserver_protocol_1.DiagnosticSeverity.Hint: - filetype = 'Hint'; - break; - case vscode_languageserver_protocol_1.DiagnosticSeverity.Warning: - filetype = 'Warning'; - break; - case vscode_languageserver_protocol_1.DiagnosticSeverity.Information: - filetype = 'Info'; - break; - } - } - else { - filetype = ft; - } - docs.push({ filetype, content: str }); - }); - if (useFloat) { - await this.floatFactory.create(docs); - } - else { - let lines = docs.map(d => d.content).join('\n').split(/\r?\n/); - if (lines.length) { - await this.nvim.command('echo ""'); - this.lastMessage = lines[0].slice(0, 30); - await workspace_1.default.echoLines(lines, truncate); - } - } + } + + [MKDIR] (dir, mode, cb) { + mkdir(dir, { + uid: this.uid, + gid: this.gid, + processUid: this.processUid, + processGid: this.processGid, + umask: this.processUmask, + preserve: this.preservePaths, + unlink: this.unlink, + cache: this.dirCache, + cwd: this.cwd, + mode: mode + }, cb) + } + + [DOCHOWN] (entry) { + // in preserve owner mode, chown if the entry doesn't match process + // in set owner mode, chown if setting doesn't match process + return this.forceChown || + this.preserveOwner && + ( typeof entry.uid === 'number' && entry.uid !== this.processUid || + typeof entry.gid === 'number' && entry.gid !== this.processGid ) + || + ( typeof this.uid === 'number' && this.uid !== this.processUid || + typeof this.gid === 'number' && this.gid !== this.processGid ) + } + + [UID] (entry) { + return uint32(this.uid, entry.uid, this.processUid) + } + + [GID] (entry) { + return uint32(this.gid, entry.gid, this.processGid) + } + + [FILE] (entry) { + const mode = entry.mode & 0o7777 || this.fmode + const stream = new fsm.WriteStream(entry.absolute, { + mode: mode, + autoClose: false + }) + stream.on('error', er => this[ONERROR](er, entry)) + + let actions = 1 + const done = er => { + if (er) + return this[ONERROR](er, entry) + + if (--actions === 0) + fs.close(stream.fd, _ => this[UNPEND]()) } - async jumpRelated() { - let diagnostics = await this.getCurrentDiagnostics(); - if (!diagnostics) - return; - let diagnostic = diagnostics.find(o => o.relatedInformation != null); - if (!diagnostic) - return; - let locations = diagnostic.relatedInformation.map(o => o.location); - if (locations.length == 1) { - await workspace_1.default.jumpTo(locations[0].uri, locations[0].range.start); - } - else if (locations.length > 1) { - await workspace_1.default.showLocations(locations); - } + + stream.on('finish', _ => { + // if futimes fails, try utimes + // if utimes fails, fail with the original error + // same for fchown/chown + const abs = entry.absolute + const fd = stream.fd + + if (entry.mtime && !this.noMtime) { + actions++ + const atime = entry.atime || new Date() + const mtime = entry.mtime + fs.futimes(fd, atime, mtime, er => + er ? fs.utimes(abs, atime, mtime, er2 => done(er2 && er)) + : done()) + } + + if (this[DOCHOWN](entry)) { + actions++ + const uid = this[UID](entry) + const gid = this[GID](entry) + fs.fchown(fd, uid, gid, er => + er ? fs.chown(abs, uid, gid, er2 => done(er2 && er)) + : done()) + } + + done() + }) + + const tx = this.transform ? this.transform(entry) || entry : entry + if (tx !== entry) { + tx.on('error', er => this[ONERROR](er, entry)) + entry.pipe(tx) } - disposeBuffer(bufnr) { - let idx = this.buffers.findIndex(buf => buf.bufnr == bufnr); - if (idx == -1) - return; - let buf = this.buffers[idx]; - buf.dispose(); - this.buffers.splice(idx, 1); - for (let collection of this.collections) { - collection.delete(buf.uri); + tx.pipe(stream) + } + + [DIRECTORY] (entry) { + const mode = entry.mode & 0o7777 || this.dmode + this[MKDIR](entry.absolute, mode, er => { + if (er) + return this[ONERROR](er, entry) + + let actions = 1 + const done = _ => { + if (--actions === 0) { + this[UNPEND]() + entry.resume() } - buf.clear().logError(); + } + + if (entry.mtime && !this.noMtime) { + actions++ + fs.utimes(entry.absolute, entry.atime || new Date(), entry.mtime, done) + } + + if (this[DOCHOWN](entry)) { + actions++ + fs.chown(entry.absolute, this[UID](entry), this[GID](entry), done) + } + + done() + }) + } + + [UNSUPPORTED] (entry) { + this.warn('unsupported entry type: ' + entry.type, entry) + entry.resume() + } + + [SYMLINK] (entry) { + this[LINK](entry, entry.linkpath, 'symlink') + } + + [HARDLINK] (entry) { + this[LINK](entry, path.resolve(this.cwd, entry.linkpath), 'link') + } + + [PEND] () { + this[PENDING]++ + } + + [UNPEND] () { + this[PENDING]-- + this[MAYBECLOSE]() + } + + [SKIP] (entry) { + this[UNPEND]() + entry.resume() + } + + // Check if we can reuse an existing filesystem entry safely and + // overwrite it, rather than unlinking and recreating + // Windows doesn't report a useful nlink, so we just never reuse entries + [ISREUSABLE] (entry, st) { + return entry.type === 'File' && + !this.unlink && + st.isFile() && + st.nlink <= 1 && + process.platform !== 'win32' + } + + // check if a thing is there, and if so, try to clobber it + [CHECKFS] (entry) { + this[PEND]() + this[MKDIR](path.dirname(entry.absolute), this.dmode, er => { + if (er) + return this[ONERROR](er, entry) + fs.lstat(entry.absolute, (er, st) => { + if (st && (this.keep || this.newer && st.mtime > entry.mtime)) + this[SKIP](entry) + else if (er || this[ISREUSABLE](entry, st)) + this[MAKEFS](null, entry) + else if (st.isDirectory()) { + if (entry.type === 'Directory') { + if (!entry.mode || (st.mode & 0o7777) === entry.mode) + this[MAKEFS](null, entry) + else + fs.chmod(entry.absolute, entry.mode, er => this[MAKEFS](er, entry)) + } else + fs.rmdir(entry.absolute, er => this[MAKEFS](er, entry)) + } else + unlinkFile(entry.absolute, er => this[MAKEFS](er, entry)) + }) + }) + } + + [MAKEFS] (er, entry) { + if (er) + return this[ONERROR](er, entry) + + switch (entry.type) { + case 'File': + case 'OldFile': + case 'ContiguousFile': + return this[FILE](entry) + + case 'Link': + return this[HARDLINK](entry) + + case 'SymbolicLink': + return this[SYMLINK](entry) + + case 'Directory': + case 'GNUDumpDir': + return this[DIRECTORY](entry) } - hideFloat() { - if (this.floatFactory) { - this.floatFactory.close(); + } + + [LINK] (entry, linkpath, link) { + // XXX: get the type ('file' or 'dir') for windows + fs[link](linkpath, entry.absolute, er => { + if (er) + return this[ONERROR](er, entry) + this[UNPEND]() + entry.resume() + }) + } +} + +class UnpackSync extends Unpack { + constructor (opt) { + super(opt) + } + + [CHECKFS] (entry) { + const er = this[MKDIR](path.dirname(entry.absolute), this.dmode) + if (er) + return this[ONERROR](er, entry) + try { + const st = fs.lstatSync(entry.absolute) + if (this.keep || this.newer && st.mtime > entry.mtime) + return this[SKIP](entry) + else if (this[ISREUSABLE](entry, st)) + return this[MAKEFS](null, entry) + else { + try { + if (st.isDirectory()) { + if (entry.type === 'Directory') { + if (entry.mode && (st.mode & 0o7777) !== entry.mode) + fs.chmodSync(entry.absolute, entry.mode) + } else + fs.rmdirSync(entry.absolute) + } else + unlinkFileSync(entry.absolute) + return this[MAKEFS](null, entry) + } catch (er) { + return this[ONERROR](er, entry) } + } + } catch (er) { + return this[MAKEFS](null, entry) } - dispose() { - for (let collection of this.collections) { - collection.dispose(); - } - if (this.floatFactory) { - this.floatFactory.dispose(); - } - this.buffers.splice(0, this.buffers.length); - this.collections = []; - util_1.disposeAll(this.disposables); + } + + [FILE] (entry) { + const mode = entry.mode & 0o7777 || this.fmode + + const oner = er => { + try { fs.closeSync(fd) } catch (_) {} + if (er) + this[ONERROR](er, entry) } - get nvim() { - return workspace_1.default.nvim; + + let stream + let fd + try { + fd = fs.openSync(entry.absolute, 'w', mode) + } catch (er) { + return oner(er) } - setConfiguration(event) { - if (event && !event.affectsConfiguration('diagnostic')) - return; - let preferences = workspace_1.default.getConfiguration('coc.preferences.diagnostic'); - let config = workspace_1.default.getConfiguration('diagnostic'); - function getConfig(key, defaultValue) { - return preferences.get(key, config.get(key, defaultValue)); - } - let messageTarget = getConfig('messageTarget', 'float'); - if (messageTarget == 'float' && !workspace_1.default.env.floating && !workspace_1.default.env.textprop) { - messageTarget = 'echo'; - } - this.config = { - messageTarget, - srcId: workspace_1.default.createNameSpace('coc-diagnostic') || 1000, - virtualTextSrcId: workspace_1.default.createNameSpace('diagnostic-virtualText'), - checkCurrentLine: getConfig('checkCurrentLine', false), - enableSign: getConfig('enableSign', true), - enableHighlightLineNumber: getConfig('enableHighlightLineNumber', true), - maxWindowHeight: getConfig('maxWindowHeight', 10), - maxWindowWidth: getConfig('maxWindowWidth', 80), - enableMessage: getConfig('enableMessage', 'always'), - joinMessageLines: getConfig('joinMessageLines', false), - messageDelay: getConfig('messageDelay', 250), - virtualText: getConfig('virtualText', false), - virtualTextPrefix: getConfig('virtualTextPrefix', " "), - virtualTextLineSeparator: getConfig('virtualTextLineSeparator', " \\ "), - virtualTextLines: getConfig('virtualTextLines', 3), - displayByAle: getConfig('displayByAle', false), - level: util_2.severityLevel(getConfig('level', 'hint')), - locationlist: getConfig('locationlist', true), - signOffset: getConfig('signOffset', 1000), - errorSign: getConfig('errorSign', '>>'), - warningSign: getConfig('warningSign', '>>'), - infoSign: getConfig('infoSign', '>>'), - hintSign: getConfig('hintSign', '>>'), - refreshAfterSave: getConfig('refreshAfterSave', false), - refreshOnInsertMode: getConfig('refreshOnInsertMode', false), - filetypeMap: getConfig('filetypeMap', {}), - format: getConfig('format', '[%source%code] [%severity] %message') - }; - this.enabled = getConfig('enable', true); - if (this.config.displayByAle) { - this.enabled = false; - } - if (event) { - for (let severity of ['error', 'info', 'warning', 'hint']) { - let key = `diagnostic.${severity}Sign`; - if (event.affectsConfiguration(key)) { - let text = config.get(`${severity}Sign`, '>>'); - let name = severity[0].toUpperCase() + severity.slice(1); - this.nvim.command(`sign define Coc${name} text=${text} linehl=Coc${name}Line texthl=Coc${name}Sign`, true); - } - } + const tx = this.transform ? this.transform(entry) || entry : entry + if (tx !== entry) { + tx.on('error', er => this[ONERROR](er, entry)) + entry.pipe(tx) + } + + tx.on('data', chunk => { + try { + fs.writeSync(fd, chunk, 0, chunk.length) + } catch (er) { + oner(er) + } + }) + + tx.on('end', _ => { + let er = null + // try both, falling futimes back to utimes + // if either fails, handle the first error + if (entry.mtime && !this.noMtime) { + const atime = entry.atime || new Date() + const mtime = entry.mtime + try { + fs.futimesSync(fd, atime, mtime) + } catch (futimeser) { + try { + fs.utimesSync(entry.absolute, atime, mtime) + } catch (utimeser) { + er = futimeser + } + } + } + + if (this[DOCHOWN](entry)) { + const uid = this[UID](entry) + const gid = this[GID](entry) + + try { + fs.fchownSync(fd, uid, gid) + } catch (fchowner) { + try { + fs.chownSync(entry.absolute, uid, gid) + } catch (chowner) { + er = er || fchowner + } } + } + + oner(er) + }) + } + + [DIRECTORY] (entry) { + const mode = entry.mode & 0o7777 || this.dmode + const er = this[MKDIR](entry.absolute, mode) + if (er) + return this[ONERROR](er, entry) + if (entry.mtime && !this.noMtime) { + try { + fs.utimesSync(entry.absolute, entry.atime || new Date(), entry.mtime) + } catch (er) {} } - getCollections(uri) { - return this.collections.filter(c => c.has(uri)); + if (this[DOCHOWN](entry)) { + try { + fs.chownSync(entry.absolute, this[UID](entry), this[GID](entry)) + } catch (er) {} } - shouldValidate(doc) { - return doc != null && doc.buftype == ''; + entry.resume() + } + + [MKDIR] (dir, mode) { + try { + return mkdir.sync(dir, { + uid: this.uid, + gid: this.gid, + processUid: this.processUid, + processGid: this.processGid, + umask: this.processUmask, + preserve: this.preservePaths, + unlink: this.unlink, + cache: this.dirCache, + cwd: this.cwd, + mode: mode + }) + } catch (er) { + return er } - refreshBuffer(uri) { - let { insertMode } = workspace_1.default; - if (insertMode && !this.config.refreshOnInsertMode) - return; - let buf = this.buffers.find(buf => buf.uri == uri); - if (!buf) - return; - let { displayByAle } = this.config; - if (!displayByAle) { - let diagnostics = this.getDiagnostics(uri); - if (this.enabled) { - buf.refresh(diagnostics); - return true; - } - } - else { - let { nvim } = this; - nvim.pauseNotification(); - for (let collection of this.collections) { - let diagnostics = collection.get(uri); - const { level } = this.config; - if (level) { - diagnostics = diagnostics.filter(o => o.severity && o.severity <= level); - } - let aleItems = diagnostics.map(o => { - let { range } = o; - return { - text: o.message, - code: o.code, - lnum: range.start.line + 1, - col: range.start.character + 1, - end_lnum: range.end.line + 1, - end_col: range.end.character, - type: util_2.getSeverityType(o.severity) - }; - }); - nvim.call('ale#other_source#ShowResults', [buf.bufnr, collection.name, aleItems], true); - } - nvim.resumeNotification(false, true).logError(); - } - return false; + } + + [LINK] (entry, linkpath, link) { + try { + fs[link + 'Sync'](linkpath, entry.absolute) + entry.resume() + } catch (er) { + return this[ONERROR](er, entry) } + } } -exports.DiagnosticManager = DiagnosticManager; -exports.default = new DiagnosticManager(); -//# sourceMappingURL=manager.js.map + +Unpack.Sync = UnpackSync +module.exports = Unpack + /***/ }), -/* 320 */ +/* 307 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const tslib_1 = __webpack_require__(3); -const vscode_languageserver_protocol_1 = __webpack_require__(150); -const events_1 = tslib_1.__importDefault(__webpack_require__(149)); -const manager_1 = tslib_1.__importDefault(__webpack_require__(248)); -const util_1 = __webpack_require__(177); -const object_1 = __webpack_require__(193); -const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const floatBuffer_1 = tslib_1.__importDefault(__webpack_require__(321)); -const debounce_1 = tslib_1.__importDefault(__webpack_require__(179)); -const popup_1 = tslib_1.__importDefault(__webpack_require__(325)); -const array_1 = __webpack_require__(215); -const logger = __webpack_require__(2)('model-float'); -// factory class for floating window -class FloatFactory { - constructor(nvim, env, preferTop = false, maxHeight = 999, maxWidth, autoHide = true) { - this.nvim = nvim; - this.env = env; - this.preferTop = preferTop; - this.maxHeight = maxHeight; - this.maxWidth = maxWidth; - this.autoHide = autoHide; - this.disposables = []; - this.alignTop = false; - this.pumAlignTop = false; - this.createTs = 0; - this.cursor = [0, 0]; - this.shown = false; - if (!workspace_1.default.floatSupported) - return; - this.maxWidth = Math.min(maxWidth || 80, this.columns - 10); - events_1.default.on('BufEnter', bufnr => { - if (this.buffer && bufnr == this.buffer.id) - return; - if (bufnr == this.targetBufnr) - return; - this.close(); - }, null, this.disposables); - events_1.default.on('InsertLeave', bufnr => { - if (this.buffer && bufnr == this.buffer.id) - return; - if (manager_1.default.isActived(bufnr)) - return; - this.close(); - }, null, this.disposables); - events_1.default.on('MenuPopupChanged', async (ev, cursorline) => { - let pumAlignTop = this.pumAlignTop = cursorline > ev.row; - if (pumAlignTop == this.alignTop) { - this.close(); - } - }, null, this.disposables); - events_1.default.on('CursorMoved', debounce_1.default((bufnr, cursor) => { - if (Date.now() - this.createTs < 100) - return; - this.onCursorMoved(false, bufnr, cursor); - }, 100), null, this.disposables); - events_1.default.on('CursorMovedI', this.onCursorMoved.bind(this, true), null, this.disposables); +// wrapper around mkdirp for tar's needs. + +// TODO: This should probably be a class, not functionally +// passing around state in a gazillion args. + +const mkdirp = __webpack_require__(182) +const fs = __webpack_require__(4) +const path = __webpack_require__(20) +const chownr = __webpack_require__(308) + +class SymlinkError extends Error { + constructor (symlink, path) { + super('Cannot extract through symbolic link') + this.path = path + this.symlink = symlink + } + + get name () { + return 'SylinkError' + } +} + +class CwdError extends Error { + constructor (path, code) { + super(code + ': Cannot cd into \'' + path + '\'') + this.path = path + this.code = code + } + + get name () { + return 'CwdError' + } +} + +const mkdir = module.exports = (dir, opt, cb) => { + // if there's any overlap between mask and mode, + // then we'll need an explicit chmod + const umask = opt.umask + const mode = opt.mode | 0o0700 + const needChmod = (mode & umask) !== 0 + + const uid = opt.uid + const gid = opt.gid + const doChown = typeof uid === 'number' && + typeof gid === 'number' && + ( uid !== opt.processUid || gid !== opt.processGid ) + + const preserve = opt.preserve + const unlink = opt.unlink + const cache = opt.cache + const cwd = opt.cwd + + const done = (er, created) => { + if (er) + cb(er) + else { + cache.set(dir, true) + if (created && doChown) + chownr(created, uid, gid, er => done(er)) + else if (needChmod) + fs.chmod(dir, mode, cb) + else + cb() } - onCursorMoved(insertMode, bufnr, cursor) { - if (!this.window || this.buffer && bufnr == this.buffer.id) - return; - if (bufnr == this.targetBufnr && object_1.equals(cursor, this.cursor)) - return; - if (this.autoHide) { - this.close(); - return; - } - if (!insertMode || bufnr != this.targetBufnr || (this.cursor && cursor[0] != this.cursor[0])) { - this.close(); - return; - } + } + + if (cache && cache.get(dir) === true) + return done() + + if (dir === cwd) + return fs.stat(dir, (er, st) => { + if (er || !st.isDirectory()) + er = new CwdError(dir, er && er.code || 'ENOTDIR') + done(er) + }) + + if (preserve) + return mkdirp(dir, mode, done) + + const sub = path.relative(cwd, dir) + const parts = sub.split(/\/|\\/) + mkdir_(cwd, parts, mode, cache, unlink, cwd, null, done) +} + +const mkdir_ = (base, parts, mode, cache, unlink, cwd, created, cb) => { + if (!parts.length) + return cb(null, created) + const p = parts.shift() + const part = base + '/' + p + if (cache.get(part)) + return mkdir_(part, parts, mode, cache, unlink, cwd, created, cb) + fs.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb)) +} + +const onmkdir = (part, parts, mode, cache, unlink, cwd, created, cb) => er => { + if (er) { + if (er.path && path.dirname(er.path) === cwd && + (er.code === 'ENOTDIR' || er.code === 'ENOENT')) + return cb(new CwdError(cwd, er.code)) + + fs.lstat(part, (statEr, st) => { + if (statEr) + cb(statEr) + else if (st.isDirectory()) + mkdir_(part, parts, mode, cache, unlink, cwd, created, cb) + else if (unlink) + fs.unlink(part, er => { + if (er) + return cb(er) + fs.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb)) + }) + else if (st.isSymbolicLink()) + return cb(new SymlinkError(part, part + '/' + parts.join('/'))) + else + cb(er) + }) + } else { + created = created || part + mkdir_(part, parts, mode, cache, unlink, cwd, created, cb) + } +} + +const mkdirSync = module.exports.sync = (dir, opt) => { + // if there's any overlap between mask and mode, + // then we'll need an explicit chmod + const umask = opt.umask + const mode = opt.mode | 0o0700 + const needChmod = (mode & umask) !== 0 + + const uid = opt.uid + const gid = opt.gid + const doChown = typeof uid === 'number' && + typeof gid === 'number' && + ( uid !== opt.processUid || gid !== opt.processGid ) + + const preserve = opt.preserve + const unlink = opt.unlink + const cache = opt.cache + const cwd = opt.cwd + + const done = (created) => { + cache.set(dir, true) + if (created && doChown) + chownr.sync(created, uid, gid) + if (needChmod) + fs.chmodSync(dir, mode) + } + + if (cache && cache.get(dir) === true) + return done() + + if (dir === cwd) { + let ok = false + let code = 'ENOTDIR' + try { + ok = fs.statSync(dir).isDirectory() + } catch (er) { + code = er.code + } finally { + if (!ok) + throw new CwdError(dir, code) } - async checkFloatBuffer() { - let { floatBuffer, nvim, window } = this; - if (this.env.textprop) { - let valid = await this.activated(); - if (!valid) - window = null; - if (!window) { - this.popup = await popup_1.default(nvim, [''], { - padding: [0, 1, 0, 1], - highlight: 'CocFloating', - tab: -1, - }); - let win = this.window = nvim.createWindow(this.popup.id); - nvim.pauseNotification(); - win.setVar('float', 1, true); - win.setOption('linebreak', true, true); - if (workspace_1.default.isVim && parseInt(workspace_1.default.env.version, 10) >= 8012281) { - win.setOption('showbreak', 'NONE', true); - } - win.setOption('conceallevel', 2, true); - await nvim.resumeNotification(); - } - let buffer = this.nvim.createBuffer(this.popup.bufferId); - this.floatBuffer = new floatBuffer_1.default(nvim, buffer, nvim.createWindow(this.popup.id)); + done() + return + } + + if (preserve) + return done(mkdirp.sync(dir, mode)) + + const sub = path.relative(cwd, dir) + const parts = sub.split(/\/|\\/) + let created = null + for (let p = parts.shift(), part = cwd; + p && (part += '/' + p); + p = parts.shift()) { + + if (cache.get(part)) + continue + + try { + fs.mkdirSync(part, mode) + created = created || part + cache.set(part, true) + } catch (er) { + if (er.path && path.dirname(er.path) === cwd && + (er.code === 'ENOTDIR' || er.code === 'ENOENT')) + return new CwdError(cwd, er.code) + + const st = fs.lstatSync(part) + if (st.isDirectory()) { + cache.set(part, true) + continue + } else if (unlink) { + fs.unlinkSync(part) + fs.mkdirSync(part, mode) + created = created || part + cache.set(part, true) + continue + } else if (st.isSymbolicLink()) + return new SymlinkError(part, part + '/' + parts.join('/')) + } + } + + return done(created) +} + + +/***/ }), +/* 308 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const fs = __webpack_require__(4) +const path = __webpack_require__(20) + +/* istanbul ignore next */ +const LCHOWN = fs.lchown ? 'lchown' : 'chown' +/* istanbul ignore next */ +const LCHOWNSYNC = fs.lchownSync ? 'lchownSync' : 'chownSync' + +// fs.readdir could only accept an options object as of node v6 +const nodeVersion = process.version +let readdir = (path, options, cb) => fs.readdir(path, options, cb) +let readdirSync = (path, options) => fs.readdirSync(path, options) +/* istanbul ignore next */ +if (/^v4\./.test(nodeVersion)) + readdir = (path, options, cb) => fs.readdir(path, cb) + +const chownrKid = (p, child, uid, gid, cb) => { + if (typeof child === 'string') + return fs.lstat(path.resolve(p, child), (er, stats) => { + if (er) + return cb(er) + stats.name = child + chownrKid(p, stats, uid, gid, cb) + }) + + if (child.isDirectory()) { + chownr(path.resolve(p, child.name), uid, gid, er => { + if (er) + return cb(er) + fs[LCHOWN](path.resolve(p, child.name), uid, gid, cb) + }) + } else + fs[LCHOWN](path.resolve(p, child.name), uid, gid, cb) +} + + +const chownr = (p, uid, gid, cb) => { + readdir(p, { withFileTypes: true }, (er, children) => { + // any error other than ENOTDIR or ENOTSUP means it's not readable, + // or doesn't exist. give up. + if (er && er.code !== 'ENOTDIR' && er.code !== 'ENOTSUP') + return cb(er) + if (er || !children.length) return fs[LCHOWN](p, uid, gid, cb) + + let len = children.length + let errState = null + const then = er => { + if (errState) return + if (er) return cb(errState = er) + if (-- len === 0) return fs[LCHOWN](p, uid, gid, cb) + } + + children.forEach(child => chownrKid(p, child, uid, gid, then)) + }) +} + +const chownrKidSync = (p, child, uid, gid) => { + if (typeof child === 'string') { + const stats = fs.lstatSync(path.resolve(p, child)) + stats.name = child + child = stats + } + + if (child.isDirectory()) + chownrSync(path.resolve(p, child.name), uid, gid) + + fs[LCHOWNSYNC](path.resolve(p, child.name), uid, gid) +} + +const chownrSync = (p, uid, gid) => { + let children + try { + children = readdirSync(p, { withFileTypes: true }) + } catch (er) { + if (er && er.code === 'ENOTDIR' && er.code !== 'ENOTSUP') + return fs[LCHOWNSYNC](p, uid, gid) + throw er + } + + if (children.length) + children.forEach(child => chownrKidSync(p, child, uid, gid)) + + return fs[LCHOWNSYNC](p, uid, gid) +} + +module.exports = chownr +chownr.sync = chownrSync + + +/***/ }), +/* 309 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const tslib_1 = __webpack_require__(3); +const follow_redirects_1 = __webpack_require__(271); +const tunnel_1 = tslib_1.__importDefault(__webpack_require__(310)); +const url_1 = __webpack_require__(269); +const zlib_1 = tslib_1.__importDefault(__webpack_require__(82)); +const is_1 = __webpack_require__(194); +const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); +const logger = __webpack_require__(2)('model-fetch'); +function getAgent(endpoint) { + let key = endpoint.protocol.startsWith('https') ? 'HTTPS_PROXY' : 'HTTP_PROXY'; + let env = process.env[key] || process.env[key.toLowerCase()]; + if (env) { + let noProxy = process.env.NO_PROXY || process.env.no_proxy; + if (noProxy === '*') { + env = null; } - else { - if (floatBuffer) { - let valid = await floatBuffer.valid; - if (valid) - return; + else if (noProxy) { + // canonicalize the hostname, so that 'oogle.com' won't match 'google.com' + const hostname = endpoint.hostname.replace(/^\.*/, '.').toLowerCase(); + const port = endpoint.port || endpoint.protocol.startsWith('https') ? '443' : '80'; + const noProxyList = noProxy.split(','); + for (let i = 0, len = noProxyList.length; i < len; i++) { + let noProxyItem = noProxyList[i].trim().toLowerCase(); + // no_proxy can be granular at the port level, which complicates things a bit. + if (noProxyItem.indexOf(':') > -1) { + let noProxyItemParts = noProxyItem.split(':', 2); + let noProxyHost = noProxyItemParts[0].replace(/^\.*/, '.'); + let noProxyPort = noProxyItemParts[1]; + if (port === noProxyPort && hostname.endsWith(noProxyHost)) { + env = null; + break; + } + } + else { + noProxyItem = noProxyItem.replace(/^\.*/, '.'); + if (hostname.endsWith(noProxyItem)) { + env = null; + break; + } + } } - let buf = await this.nvim.createNewBuffer(false, true); - await buf.setOption('buftype', 'nofile'); - await buf.setOption('bufhidden', 'hide'); - this.floatBuffer = new floatBuffer_1.default(this.nvim, buf); } } - get columns() { - return this.env.columns; - } - get lines() { - return this.env.lines - this.env.cmdheight - 1; + let proxy = workspace_1.default.getConfiguration('http').get('proxy', ''); + if (!proxy && env) { + proxy = env; } - async getBoundings(docs, offsetX = 0) { - let { nvim, preferTop } = this; - let { columns, lines } = this; - let alignTop = false; - let [row, col] = await nvim.call('coc#util#win_position'); - let maxWidth = this.maxWidth; - let height = this.floatBuffer.getHeight(docs, maxWidth); - height = Math.min(height, this.maxHeight); - if (!preferTop) { - if (lines - row < height && row > height) { - alignTop = true; - } - } - else { - if (row >= height || row >= lines - row) { - alignTop = true; - } - } - if (alignTop) - docs.reverse(); - await this.floatBuffer.setDocuments(docs, maxWidth); - let { width } = this.floatBuffer; - // Ensure the floating window isn't tiny if the cursor is on the right: - // increase the offset to accommodate some minimum width. - // If we have offsetX, precise positioning is intended, force exact width. - let minWidth = offsetX ? width : Math.min(width, 50, maxWidth); - offsetX = Math.min(col - 1, offsetX); - if (col - offsetX + minWidth > columns) { - offsetX = col - offsetX + minWidth - columns; + if (proxy) { + proxy = proxy.replace(/^https?:\/\//, '').replace(/\/$/, ''); + let auth = proxy.includes('@') ? proxy.split('@', 2)[0] : ''; + let parts = auth.length ? proxy.slice(auth.length + 1).split(':') : proxy.split(':'); + logger.info(`Using proxy from: ${proxy}`); + if (parts.length > 1) { + let agent = tunnel_1.default.httpsOverHttp({ + proxy: { + headers: {}, + host: parts[0], + port: parseInt(parts[1], 10), + proxyAuth: auth + } + }); + return agent; } - this.alignTop = alignTop; - return { - height: alignTop ? Math.max(1, Math.min(row, height)) : Math.max(1, Math.min(height, (lines - row))), - width: Math.min(columns, width), - row: alignTop ? -height : 1, - col: offsetX == 0 ? 0 : -offsetX, - relative: 'cursor' - }; } - async create(docs, allowSelection = false, offsetX = 0) { - if (!workspace_1.default.floatSupported) { - logger.error('Floating window & textprop not supported!'); - return; +} +exports.getAgent = getAgent; +/** + * Fetch text from server + */ +function fetch(url, data, options = {}) { + logger.info('fetch:', url); + let mod = url.startsWith('https') ? follow_redirects_1.https : follow_redirects_1.http; + let endpoint = url_1.parse(url); + let agent = getAgent(endpoint); + let opts = Object.assign({ + method: 'GET', + hostname: endpoint.hostname, + port: endpoint.port ? parseInt(endpoint.port, 10) : (endpoint.protocol === 'https:' ? 443 : 80), + path: endpoint.path, + protocol: url.startsWith('https') ? 'https:' : 'http:', + agent, + headers: { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64)', + 'Accept-Encoding': 'gzip' } - let shown = await this.createPopup(docs, allowSelection, offsetX); - if (!shown) - this.close(false); + }, options); + if (data && is_1.objectLiteral(data)) { + opts.headers['Content-Type'] = 'application/json'; } - async createPopup(docs, allowSelection = false, offsetX = 0) { - if (this.tokenSource) { - this.tokenSource.cancel(); - } - if (docs.length == 0) - return false; - this.createTs = Date.now(); - this.targetBufnr = workspace_1.default.bufnr; - let tokenSource = this.tokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource(); - let token = tokenSource.token; - await this.checkFloatBuffer(); - let config = await this.getBoundings(docs, offsetX); - let [mode, line, col, visible] = await this.nvim.eval('[mode(),line("."),col("."),pumvisible()]'); - this.cursor = [line, col]; - if (visible && this.alignTop == this.pumAlignTop) - return false; - if (!config || token.isCancellationRequested) - return false; - if (!this.checkMode(mode, allowSelection)) - return false; - let { nvim, alignTop } = this; - if (mode == 's') - await nvim.call('feedkeys', ['\x1b', 'in']); - // helps to fix undo issue, don't know why. - if (workspace_1.default.isNvim && mode.startsWith('i')) - await nvim.eval('feedkeys("\\u", "n")'); - let reuse = false; - if (workspace_1.default.isNvim) { - reuse = this.window && await this.window.valid; - if (!reuse) - this.window = await nvim.openFloatWindow(this.buffer, false, config); - } - if (token.isCancellationRequested) - return false; - nvim.pauseNotification(); - if (workspace_1.default.isNvim) { - if (!reuse) { - nvim.command(`noa call win_gotoid(${this.window.id})`, true); - this.window.setVar('float', 1, true); - nvim.command(`setl nospell nolist wrap linebreak foldcolumn=1 showbreak=`, true); - nvim.command(`setl nonumber norelativenumber nocursorline nocursorcolumn colorcolumn=`, true); - nvim.command(`setl signcolumn=no conceallevel=2 concealcursor=n`, true); - nvim.command(`setl winhl=Normal:CocFloating,NormalNC:CocFloating,FoldColumn:CocFloating`, true); - nvim.call('coc#util#do_autocmd', ['CocOpenFloat'], true); - } - else { - this.window.setConfig(config, true); - nvim.command(`noa call win_gotoid(${this.window.id})`, true); - } - this.floatBuffer.setLines(); - nvim.command(`normal! ${alignTop ? 'G' : 'gg'}0`, true); - nvim.command('noa wincmd p', true); - } - else { - let filetypes = array_1.distinct(docs.map(d => d.filetype)); - if (filetypes.length == 1) { - this.popup.setFiletype(filetypes[0]); - } - this.popup.move({ - line: cursorPostion(config.row), - col: cursorPostion(config.col), - minwidth: config.width - 2, - minheight: config.height, - maxwidth: config.width - 2, - maxheight: this.maxHeight, - firstline: alignTop ? -1 : 1 + if (data && !opts.method) { + opts.method = 'POST'; + } + return new Promise((resolve, reject) => { + // tslint:disable-next-line: only-arrow-functions + try { + const req = mod.request(opts, res => { + let readable = res; + if (res.statusCode != 200) { + reject(new Error(`Invalid response from ${url}: ${res.statusCode}`)); + return; + } + let chunks = []; + let contentType = res.headers['content-type']; + let contentEncoding = res.headers['content-encoding']; + let ms = contentType.match(/charset=(\S+)/); + let encoding = ms ? ms[1] : 'utf8'; + if (contentEncoding == 'gzip') { + const unzip = zlib_1.default.createGunzip(); + readable = res.pipe(unzip); + } + readable.on('data', chunk => { + chunks.push(chunk); + }); + readable.on('end', () => { + let buf = Buffer.concat(chunks); + let rawData = buf.toString(encoding); + if (/^application\/json/.test(contentType)) { + try { + const parsedData = JSON.parse(rawData); + resolve(parsedData); + } + catch (e) { + reject(`Parse error: ${e}`); + } + } + else { + resolve(rawData); + } + }); }); - this.floatBuffer.setLines(); - nvim.command('redraw', true); + req.on('error', reject); + if (data) { + if (typeof data == 'string') { + req.write(data); + } + else { + req.write(JSON.stringify(data)); + } + } + req.end(); } - let [, err] = await nvim.resumeNotification(); - if (err) { - workspace_1.default.showMessage(`Error on ${err[0]}: ${err[1]} - ${err[2]}`, 'error'); - return false; + catch (e) { + logger.error(e); + reject(e); } - if (mode == 's') - await manager_1.default.selectCurrentPlaceholder(false); - return true; + }); +} +exports.default = fetch; +//# sourceMappingURL=fetch.js.map + +/***/ }), +/* 310 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = __webpack_require__(311); + + +/***/ }), +/* 311 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var net = __webpack_require__(96); +var tls = __webpack_require__(312); +var http = __webpack_require__(272); +var https = __webpack_require__(273); +var events = __webpack_require__(137); +var assert = __webpack_require__(46); +var util = __webpack_require__(12); + + +exports.httpOverHttp = httpOverHttp; +exports.httpsOverHttp = httpsOverHttp; +exports.httpOverHttps = httpOverHttps; +exports.httpsOverHttps = httpsOverHttps; + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + return agent; +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + return agent; +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + + +function TunnelingAgent(options) { + var self = this; + self.options = options || {}; + self.proxyOptions = self.options.proxy || {}; + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; + self.requests = []; + self.sockets = []; + + self.on('free', function onFree(socket, host, port, localAddress) { + var options = toOptions(host, port, localAddress); + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i]; + if (pending.host === options.host && pending.port === options.port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1); + pending.request.onSocket(socket); + return; + } } - checkMode(mode, allowSelection) { - if (mode == 's' && allowSelection) { - return true; - } - return ['i', 'n', 'ic'].indexOf(mode) != -1; + socket.destroy(); + self.removeSocket(socket); + }); +} +util.inherits(TunnelingAgent, events.EventEmitter); + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { + var self = this; + var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push(options); + return; + } + + // If we are under maxSockets create a new one. + self.createSocket(options, function(socket) { + socket.on('free', onFree); + socket.on('close', onCloseOrRemove); + socket.on('agentRemove', onCloseOrRemove); + req.onSocket(socket); + + function onFree() { + self.emit('free', socket, options); } - /** - * Close float window - */ - close(cancel = true) { - if (cancel && this.tokenSource) { - if (this.tokenSource) { - this.tokenSource.cancel(); - this.tokenSource = null; - } - } - let { window, popup } = this; - this.shown = false; - if (this.env.textprop) { - if (popup) - popup.dispose(); - } - else if (window) { - window.close(true, true); - } + + function onCloseOrRemove(err) { + self.removeSocket(socket); + socket.removeListener('free', onFree); + socket.removeListener('close', onCloseOrRemove); + socket.removeListener('agentRemove', onCloseOrRemove); } - dispose() { - if (this.tokenSource) { - this.tokenSource.cancel(); - } - util_1.disposeAll(this.disposables); + }); +}; + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this; + var placeholder = {}; + self.sockets.push(placeholder); + + var connectOptions = mergeOptions({}, self.proxyOptions, { + method: 'CONNECT', + path: options.host + ':' + options.port, + agent: false, + headers: { + host: options.host + ':' + options.port } - get buffer() { - return this.floatBuffer ? this.floatBuffer.buffer : null; + }); + if (options.localAddress) { + connectOptions.localAddress = options.localAddress; + } + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {}; + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64'); + } + + debug('making CONNECT request'); + var connectReq = self.request(connectOptions); + connectReq.useChunkedEncodingByDefault = false; // for v0.6 + connectReq.once('response', onResponse); // for v0.6 + connectReq.once('upgrade', onUpgrade); // for v0.6 + connectReq.once('connect', onConnect); // for v0.7 or later + connectReq.once('error', onError); + connectReq.end(); + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true; + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head); + }); + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners(); + socket.removeAllListeners(); + + if (res.statusCode !== 200) { + debug('tunneling socket could not be established, statusCode=%d', + res.statusCode); + socket.destroy(); + var error = new Error('tunneling socket could not be established, ' + + 'statusCode=' + res.statusCode); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; } - async activated() { - if (this.env.textprop) { - if (!this.popup) - return false; - return await this.popup.visible(); + if (head.length > 0) { + debug('got illegal response body from proxy'); + socket.destroy(); + var error = new Error('got illegal response body from proxy'); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + debug('tunneling connection has established'); + self.sockets[self.sockets.indexOf(placeholder)] = socket; + return cb(socket); + } + + function onError(cause) { + connectReq.removeAllListeners(); + + debug('tunneling socket could not be established, cause=%s\n', + cause.message, cause.stack); + var error = new Error('tunneling socket could not be established, ' + + 'cause=' + cause.message); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + } +}; + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) { + return; + } + this.sockets.splice(pos, 1); + + var pending = this.requests.shift(); + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket); + }); + } +}; + +function createSecureSocket(options, cb) { + var self = this; + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + var hostHeader = options.request.getHeader('host'); + var tlsOptions = mergeOptions({}, self.options, { + socket: socket, + servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host + }); + + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, tlsOptions); + self.sockets[self.sockets.indexOf(socket)] = secureSocket; + cb(secureSocket); + }); +} + + +function toOptions(host, port, localAddress) { + if (typeof host === 'string') { // since v0.10 + return { + host: host, + port: port, + localAddress: localAddress + }; + } + return host; // for v0.11 or later +} + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i]; + if (typeof overrides === 'object') { + var keys = Object.keys(overrides); + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j]; + if (overrides[k] !== undefined) { + target[k] = overrides[k]; } - if (!this.window) - return false; - let valid = await this.window.valid; - return valid; + } } + } + return target; } -exports.default = FloatFactory; -function cursorPostion(n) { - if (n == 0) - return 'cursor'; - if (n < 0) - return `cursor${n}`; - return `cursor+${n}`; + + +var debug; +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments); + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0]; + } else { + args.unshift('TUNNEL:'); + } + console.error.apply(console, args); + } +} else { + debug = function() {}; } -//# sourceMappingURL=floatFactory.js.map +exports.debug = debug; // for test + /***/ }), -/* 321 */ +/* 312 */ +/***/ (function(module, exports) { + +module.exports = require("tls"); + +/***/ }), +/* 313 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); -const highlight_1 = __webpack_require__(322); -const string_1 = __webpack_require__(213); -const array_1 = __webpack_require__(215); -const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const logger = __webpack_require__(2)('model-floatBuffer'); -class FloatBuffer { - constructor(nvim, buffer, window) { - this.nvim = nvim; - this.buffer = buffer; - this.window = window; - this.lines = []; - this.positions = []; - this.enableHighlight = true; - this.highlightTimeout = 500; - this.tabstop = 2; - this.width = 0; - let config = workspace_1.default.getConfiguration('coc.preferences'); - this.enableHighlight = config.get('enableFloatHighlight', true); - this.highlightTimeout = config.get('highlightTimeout', 500); - buffer.getOption('tabstop').then(val => { - this.tabstop = val; - }, _e => { - // noop - }); - } - getHeight(docs, maxWidth) { - let l = 0; - for (let doc of docs) { - let lines = doc.content.split(/\r?\n/); - if (doc.filetype == 'markdown') { - lines = lines.filter(s => !s.startsWith('```')); - } - for (let line of lines) { - l = l + Math.max(1, Math.ceil(string_1.byteLength(line) / (maxWidth - 4))); - } - } - return l + docs.length - 1; - } - get valid() { - return this.buffer.valid; - } - calculateFragments(docs, maxWidth) { - let fragments = []; - let idx = 0; - let currLine = 0; - let newLines = []; - let fill = false; - let positions = this.positions = []; - for (let doc of docs) { - let lines = []; - let content = doc.content.replace(/\s+$/, ''); - let arr = content.split(/\r?\n/); - if (['Error', 'Info', 'Warning', 'Hint'].indexOf(doc.filetype) !== -1) { - fill = true; - } - // let [start, end] = doc.active || [] - for (let str of arr) { - lines.push(str); - if (doc.active) { - let part = str.slice(doc.active[0], doc.active[1]); - positions.push([currLine + 1, doc.active[0] + 1, string_1.byteLength(part)]); - } - } - fragments.push({ - start: currLine, - lines, - filetype: doc.filetype - }); - newLines.push(...lines.filter(s => !/^\s*```/.test(s))); - if (idx != docs.length - 1) { - newLines.push('—'); - currLine = newLines.length; - } - idx = idx + 1; +const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); +const object_1 = __webpack_require__(193); +const logger = __webpack_require__(2)('model-memos'); +class Memos { + constructor(filepath) { + this.filepath = filepath; + if (!fs_1.default.existsSync(filepath)) { + fs_1.default.writeFileSync(filepath, '{}', 'utf8'); } - let width = this.width = Math.min(Math.max(...newLines.map(s => this.getWidth(s))) + 2, maxWidth); - this.lines = newLines.map(s => { - if (s == '—') - return '—'.repeat(width - 2); - return s; - }); - return fragments; } - getWidth(line) { - let { tabstop } = this; - line = line.replace(/\t/g, ' '.repeat(tabstop)); - return string_1.byteLength(line); - } - async setDocuments(docs, maxWidth) { - let fragments = this.calculateFragments(docs, maxWidth); - let filetype = await this.nvim.eval('&filetype'); - if (workspace_1.default.isNvim) { - fragments = fragments.reduce((p, c) => { - p.push(...this.splitFragment(c, filetype)); - return p; - }, []); - } - if (this.enableHighlight) { - let arr = await Promise.all(fragments.map(f => { - return highlight_1.getHiglights(f.lines, f.filetype, this.highlightTimeout).then(highlights => { - return highlights.map(highlight => { - return Object.assign({}, highlight, { line: highlight.line + f.start }); - }); - }); - })); - this.highlights = arr.reduce((p, c) => p.concat(c), []); + fetchContent(id, key) { + try { + let content = fs_1.default.readFileSync(this.filepath, 'utf8'); + let res = JSON.parse(content); + let obj = res[id]; + if (!obj) + return undefined; + return obj[key]; } - else { - this.highlights = []; + catch (e) { + return undefined; } } - splitFragment(fragment, defaultFileType) { - let res = []; - let filetype = fragment.filetype; - let lines = []; - let curr = fragment.start; - let inBlock = false; - for (let line of fragment.lines) { - let ms = line.match(/^\s*```\s*(\w+)?/); - if (ms != null) { - if (lines.length) { - res.push({ lines, filetype: this.fixFiletype(filetype), start: curr - lines.length }); - lines = []; - } - inBlock = !inBlock; - filetype = inBlock ? ms[1] || defaultFileType : fragment.filetype; + async update(id, key, value) { + let { filepath } = this; + try { + let content = fs_1.default.readFileSync(filepath, 'utf8'); + let current = content ? JSON.parse(content) : {}; + current[id] = current[id] || {}; + if (value !== undefined) { + current[id][key] = object_1.deepClone(value); } else { - lines.push(line); - curr = curr + 1; + delete current[id][key]; } + content = JSON.stringify(current, null, 2); + fs_1.default.writeFileSync(filepath, content, 'utf8'); } - if (lines.length) { - res.push({ lines, filetype: this.fixFiletype(filetype), start: curr - lines.length }); - lines = []; + catch (e) { + logger.error(`Error on update memos:`, e); } - return res; - } - fixFiletype(filetype) { - if (filetype == 'ts') - return 'typescript'; - if (filetype == 'js') - return 'javascript'; - if (filetype == 'bash') - return 'sh'; - return filetype; } - setLines() { - let { buffer, lines, nvim, highlights } = this; - nvim.call('clearmatches', this.window ? [this.window.id] : [], true); - buffer.clearNamespace(-1, 0, -1); - buffer.setLines(lines, { start: 0, end: -1, strictIndexing: false }, true); - if (highlights.length) { - let positions = []; - for (let highlight of highlights) { - buffer.addHighlight(Object.assign({ srcId: workspace_1.default.createNameSpace('coc-float') }, highlight)).catch(_e => { - // noop - }); - if (highlight.isMarkdown) { - let line = lines[highlight.line]; - if (line) { - let before = line[string_1.characterIndex(line, highlight.colStart)]; - let after = line[string_1.characterIndex(line, highlight.colEnd) - 1]; - if (before == after && ['_', '`', '*'].indexOf(before) !== -1) { - positions.push([highlight.line + 1, highlight.colStart + 1]); - positions.push([highlight.line + 1, highlight.colEnd]); - } - if (highlight.colEnd - highlight.colStart == 2 && before == '\\') { - positions.push([highlight.line + 1, highlight.colStart + 1]); - } - } - } - } - for (let arr of array_1.group(positions, 8)) { - if (this.window) { - nvim.call('win_execute', [this.window.id, `call matchaddpos('Conceal', ${JSON.stringify(arr)},11)`], true); - } - else { - nvim.call('matchaddpos', ['Conceal', arr, 11], true); - } - } - } - for (let arr of array_1.group(this.positions || [], 8)) { - arr = arr.filter(o => o[2] != 0); - if (arr.length) { - if (this.window) { - nvim.call('win_execute', [this.window.id, `call matchaddpos('CocUnderline', ${JSON.stringify(arr)},12)`], true); - } - else { - nvim.call('matchaddpos', ['CocUnderline', arr, 12], true); - } + createMemento(id) { + return { + get: (key, defaultValue) => { + let res = this.fetchContent(id, key); + return res === undefined ? defaultValue : res; + }, + update: async (key, value) => { + await this.update(id, key, value); } - } + }; } } -exports.default = FloatBuffer; -//# sourceMappingURL=floatBuffer.js.map +exports.default = Memos; +//# sourceMappingURL=memos.js.map /***/ }), -/* 322 */ +/* 314 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const tslib_1 = __webpack_require__(3); -const neovim_1 = __webpack_require__(94); -const cp = tslib_1.__importStar(__webpack_require__(178)); -const crypto_1 = __webpack_require__(160); -const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const path_1 = tslib_1.__importDefault(__webpack_require__(20)); -const lodash_1 = __webpack_require__(315); -const os_1 = tslib_1.__importDefault(__webpack_require__(14)); -const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); -const string_1 = __webpack_require__(213); -const processes_1 = __webpack_require__(323); -const uuid = __webpack_require__(324); -const logger = __webpack_require__(2)('util-highlights'); -const diagnosticFiletypes = ['Error', 'Warning', 'Info', 'Hint']; -const cache = {}; -let env = null; -// get highlights by send text to another neovim instance. -function getHiglights(lines, filetype, timeout = 500) { - const hlMap = new Map(); - const content = lines.join('\n'); - if (diagnosticFiletypes.indexOf(filetype) != -1) { - let highlights = lines.map((line, i) => { - return { - line: i, - colStart: 0, - colEnd: string_1.byteLength(line), - hlGroup: `Coc${filetype}Float` - }; - }); - return Promise.resolve(highlights); - } - if (filetype == 'javascriptreact') { - filetype = 'javascript'; - } - if (filetype == 'typescriptreact') { - filetype = 'typescript'; - } - const id = crypto_1.createHash('md5').update(content).digest('hex'); - if (cache[id]) - return Promise.resolve(cache[id]); - if (workspace_1.default.env.isVim) - return Promise.resolve([]); - const res = []; - let nvim; - return new Promise(async (resolve) => { - if (!env) { - env = await workspace_1.default.nvim.call('coc#util#highlight_options'); - if (!env) - resolve([]); - let paths = env.runtimepath.split(','); - let dirs = paths.filter(p => { - if (env.colorscheme) { - let schemeFile = path_1.default.join(p, `colors/${env.colorscheme}.vim`); - if (fs_1.default.existsSync(schemeFile)) - return true; - } - if (fs_1.default.existsSync(path_1.default.join(p, 'syntax'))) - return true; - if (fs_1.default.existsSync(path_1.default.join(p, 'after/syntax'))) - return true; - return false; - }); - env.runtimepath = dirs.join(','); - } - let prog = workspace_1.default.env.progpath || 'nvim'; - let proc = cp.spawn(prog, ['-u', 'NORC', '-i', 'NONE', '--embed', '--noplugin', uuid()], { - shell: false, - cwd: os_1.default.tmpdir(), - env: lodash_1.omit(process.env, ['NVIM_LISTEN_ADDRESS', 'VIM_NODE_RPC']) - }); - proc.on('error', error => { - logger.info('highlight error:', error); - resolve([]); - }); - let timer; - let exited = false; - const exit = () => { - if (exited) - return; - exited = true; - if (timer) - clearTimeout(timer); - if (nvim) { - nvim.command('qa!').catch(() => { - let killed = processes_1.terminate(proc); - if (!killed) { - setTimeout(() => { - processes_1.terminate(proc); - }, 50); - } - }); - } - }; - try { - proc.once('exit', () => { - if (exited) - return; - logger.info('highlight nvim exited.'); - resolve([]); - }); - timer = setTimeout(() => { - exit(); - resolve([]); - }, timeout); - nvim = neovim_1.attach({ proc }, null, false); - const callback = (method, args) => { - if (method == 'redraw') { - for (let arr of args) { - let [name, ...list] = arr; - if (name == 'hl_attr_define') { - for (let item of list) { - let id = item[0]; - let { hi_name } = item[item.length - 1][0]; - hlMap.set(id, hi_name); - } - } - if (name == 'grid_line') { - // logger.debug('list:', JSON.stringify(list, null, 2)) - for (let def of list) { - let [, line, col, cells] = def; - if (line >= lines.length) - continue; - let colStart = 0; - let hlGroup = ''; - let currId = 0; - // tslint:disable-next-line: prefer-for-of - for (let i = 0; i < cells.length; i++) { - let cell = cells[i]; - let [ch, hlId, repeat] = cell; - repeat = repeat || 1; - let len = string_1.byteLength(ch.repeat(repeat)); - // append result - if (hlId == 0 || (hlId > 0 && hlId != currId)) { - if (hlGroup) { - res.push({ - line, - hlGroup, - colStart, - colEnd: col, - isMarkdown: filetype == 'markdown' - }); - } - colStart = col; - hlGroup = hlId == 0 ? '' : hlMap.get(hlId); - } - if (hlId != null) - currId = hlId; - col = col + len; - } - if (hlGroup) { - res.push({ - hlGroup, - line, - colStart, - colEnd: col, - isMarkdown: filetype == 'markdown' - }); - } - } - cache[id] = res; - exit(); - resolve(res); - } - } - } - }; - nvim.on('notification', callback); - await nvim.callAtomic([ - ['nvim_set_option', ['runtimepath', env.runtimepath]], - ['nvim_command', [`highlight! link Normal CocFloating`]], - ['nvim_command', [`runtime syntax/${filetype}.vim`]], - ['nvim_command', [`colorscheme ${env.colorscheme || 'default'}`]], - ['nvim_command', [`set background=${env.background}`]], - ['nvim_command', ['set nowrap']], - ['nvim_command', ['set noswapfile']], - ['nvim_command', ['set nobackup']], - ['nvim_command', ['set noshowmode']], - ['nvim_command', ['set noruler']], - ['nvim_command', ['set laststatus=0']], - ]); - let buf = await nvim.buffer; - await buf.setLines(lines, { start: 0, end: -1, strictIndexing: false }); - await buf.setOption('filetype', filetype); - await nvim.uiAttach(200, lines.length + 1, { - ext_hlstate: true, - ext_linegrid: true - }); - } - catch (e) { - logger.error(e); - exit(); - resolve([]); - } +const logger = __webpack_require__(2)('extensions'); +/** + * Explicitly tells that promise should be run asynchonously. + */ +Promise.prototype.logError = function () { + // tslint:disable-next-line:no-empty + this.catch(e => { + logger.error(e); }); -} -exports.getHiglights = getHiglights; -//# sourceMappingURL=highlight.js.map +}; +//# sourceMappingURL=extensions.js.map /***/ }), -/* 323 */ +/* 315 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -const cp = tslib_1.__importStar(__webpack_require__(178)); -const path_1 = __webpack_require__(20); -const isWebpack = typeof __webpack_require__ === "function"; -const isWindows = process.platform === 'win32'; -const isMacintosh = process.platform === 'darwin'; -const isLinux = process.platform === 'linux'; -const pluginRoot = isWebpack ? path_1.dirname(__dirname) : path_1.resolve(__dirname, '../..'); -function terminate(process, cwd) { - if (isWindows) { - try { - // This we run in Atom execFileSync is available. - // Ignore stderr since this is otherwise piped to parent.stderr - // which might be already closed. - let options = { - stdio: ['pipe', 'pipe', 'ignore'] - }; - if (cwd) { - options.cwd = cwd; - } - cp.execFileSync('taskkill', ['/T', '/F', '/PID', process.pid.toString()], options); - return true; +const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); +const path = tslib_1.__importStar(__webpack_require__(20)); +const vm = tslib_1.__importStar(__webpack_require__(316)); +const lodash_1 = __webpack_require__(317); +const createLogger = __webpack_require__(2); +const logger = createLogger('util-factoroy'); +const requireFunc = true ? require : undefined; +const Module = __webpack_require__(318); +const REMOVED_GLOBALS = [ + 'reallyExit', + 'abort', + 'chdir', + 'umask', + 'setuid', + 'setgid', + 'setgroups', + '_fatalException', + 'exit', + 'kill', +]; +function removedGlobalStub(name) { + return () => { + throw new Error(`process.${name}() is not allowed in extension sandbox`); + }; +} +// @see node/lib/internal/module.js +function makeRequireFunction() { + const req = (p) => { + if (p === 'coc.nvim') { + return __webpack_require__(319); } - catch (err) { - return false; + return this.require(p); + }; + req.resolve = (request) => Module._resolveFilename(request, this); + req.main = process.mainModule; + // Enable support to add extra extension types + req.extensions = Module._extensions; + req.cache = Module._cache; + return req; +} +// @see node/lib/module.js +function compileInSandbox(sandbox) { + // eslint-disable-next-line + return function (content, filename) { + const require = makeRequireFunction.call(this); + const dirname = path.dirname(filename); + // remove shebang + // eslint-disable-next-line + const newContent = content.replace(/^\#\!.*/, ''); + const wrapper = Module.wrap(newContent); + const compiledWrapper = vm.runInContext(wrapper, sandbox, { filename }); + const args = [this.exports, require, this, filename, dirname]; + return compiledWrapper.apply(this.exports, args); + }; +} +function createSandbox(filename, logger) { + const module = new Module(filename); + module.paths = Module._nodeModulePaths(filename); + const sandbox = vm.createContext({ + module, + Buffer, + console: { + debug: (...args) => { + logger.debug.apply(logger, args); + }, + log: (...args) => { + logger.debug.apply(logger, args); + }, + error: (...args) => { + logger.error.apply(logger, args); + }, + info: (...args) => { + logger.info.apply(logger, args); + }, + warn: (...args) => { + logger.warn.apply(logger, args); + } } + }); + lodash_1.defaults(sandbox, global); + sandbox.Reflect = Reflect; + sandbox.require = function sandboxRequire(p) { + const oldCompile = Module.prototype._compile; + Module.prototype._compile = compileInSandbox(sandbox); + const moduleExports = sandbox.module.require(p); + Module.prototype._compile = oldCompile; + return moduleExports; + }; + // patch `require` in sandbox to run loaded module in sandbox context + // if you need any of these, it might be worth discussing spawning separate processes + sandbox.process = new process.constructor(); + for (let key of Object.keys(process)) { + sandbox.process[key] = process[key]; } - else if (isLinux || isMacintosh) { - try { - let cmd = path_1.join(pluginRoot, 'bin/terminateProcess.sh'); - let result = cp.spawnSync(cmd, [process.pid.toString()]); - return result.error ? false : true; - } - catch (err) { - return false; + REMOVED_GLOBALS.forEach(name => { + sandbox.process[name] = removedGlobalStub(name); + }); + // read-only umask + sandbox.process.umask = (mask) => { + if (typeof mask !== 'undefined') { + throw new Error('Cannot use process.umask() to change mask (read-only)'); } + return process.umask(); + }; + return sandbox; +} +// inspiration drawn from Module +function createExtension(id, filename) { + if (!fs_1.default.existsSync(filename)) { + // tslint:disable-next-line:no-empty + return { activate: () => { }, deactivate: null }; } - else { - process.kill('SIGKILL'); - return true; + const sandbox = createSandbox(filename, createLogger(`extension-${id}`)); + delete Module._cache[requireFunc.resolve(filename)]; + // attempt to import plugin + // Require plugin to export activate & deactivate + const defaultImport = sandbox.require(filename); + const activate = (defaultImport && defaultImport.activate) || defaultImport; + if (typeof activate !== 'function') { + // tslint:disable-next-line:no-empty + return { activate: () => { }, deactivate: null }; } + return { + activate, + deactivate: typeof defaultImport.deactivate === 'function' ? defaultImport.deactivate : null + }; } -exports.terminate = terminate; -//# sourceMappingURL=processes.js.map +exports.createExtension = createExtension; +//# sourceMappingURL=factory.js.map /***/ }), -/* 324 */ -/***/ (function(module, exports, __webpack_require__) { +/* 316 */ +/***/ (function(module, exports) { -var rng = __webpack_require__(224); -var bytesToUuid = __webpack_require__(225); +module.exports = require("vm"); -function v4(options, buf, offset) { - var i = buf && offset || 0; +/***/ }), +/* 317 */ +/***/ (function(module, exports, __webpack_require__) { - if (typeof(options) == 'string') { - buf = options === 'binary' ? new Array(16) : null; - options = null; - } - options = options || {}; +"use strict"; - var rnds = options.random || (options.rng || rng)(); +Object.defineProperty(exports, "__esModule", { value: true }); +/** Used for built-in method references. */ +const objectProto = Object.prototype; +/** Used to check objects for own properties. */ +const hasOwnProperty = objectProto.hasOwnProperty; +/** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @since 0.1.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see defaultsDeep + * @example + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }) + * // => { 'a': 1, 'b': 2 } + */ +function defaults(obj, ...sources) { + obj = Object(obj); + sources.forEach(source => { + if (source != null) { + source = Object(source); + for (const key in source) { // tslint:disable-line + const value = obj[key]; + if (value === undefined || + (value === objectProto[key] && !hasOwnProperty.call(obj, key))) { + obj[key] = source[key]; + } + } + } + }); + return obj; +} +exports.defaults = defaults; +function omit(obj, properties) { + let o = {}; + for (let key of Object.keys(obj)) { + if (properties.indexOf(key) == -1) { + o[key] = obj[key]; + } + } + return o; +} +exports.omit = omit; +//# sourceMappingURL=lodash.js.map - // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - rnds[6] = (rnds[6] & 0x0f) | 0x40; - rnds[8] = (rnds[8] & 0x3f) | 0x80; +/***/ }), +/* 318 */ +/***/ (function(module, exports) { - // Copy bytes to buffer, if provided - if (buf) { - for (var ii = 0; ii < 16; ++ii) { - buf[i + ii] = rnds[ii]; - } - } +module.exports = require("module"); - return buf || bytesToUuid(rnds); -} +/***/ }), +/* 319 */ +/***/ (function(module, exports, __webpack_require__) { -module.exports = v4; +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const tslib_1 = __webpack_require__(3); +const commands_1 = tslib_1.__importDefault(__webpack_require__(247)); +exports.commands = commands_1.default; +const events_1 = tslib_1.__importDefault(__webpack_require__(149)); +exports.events = events_1.default; +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); +exports.languages = languages_1.default; +const document_1 = tslib_1.__importDefault(__webpack_require__(210)); +exports.Document = document_1.default; +const mru_1 = tslib_1.__importDefault(__webpack_require__(218)); +exports.Mru = mru_1.default; +const floatBuffer_1 = tslib_1.__importDefault(__webpack_require__(344)); +exports.FloatBuffer = floatBuffer_1.default; +const floatFactory_1 = tslib_1.__importDefault(__webpack_require__(249)); +exports.FloatFactory = floatFactory_1.default; +const fetch_1 = tslib_1.__importDefault(__webpack_require__(309)); +exports.fetch = fetch_1.default; +const download_1 = tslib_1.__importDefault(__webpack_require__(270)); +exports.download = download_1.default; +const highligher_1 = tslib_1.__importDefault(__webpack_require__(347)); +exports.Highligher = highligher_1.default; +const fileSystemWatcher_1 = tslib_1.__importDefault(__webpack_require__(217)); +exports.FileSystemWatcher = fileSystemWatcher_1.default; +const services_1 = tslib_1.__importDefault(__webpack_require__(349)); +exports.services = services_1.default; +const sources_1 = tslib_1.__importDefault(__webpack_require__(254)); +exports.sources = sources_1.default; +const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); +exports.workspace = workspace_1.default; +const extensions_1 = tslib_1.__importDefault(__webpack_require__(255)); +exports.extensions = extensions_1.default; +const manager_1 = tslib_1.__importDefault(__webpack_require__(365)); +exports.listManager = manager_1.default; +const manager_2 = tslib_1.__importDefault(__webpack_require__(250)); +exports.snippetManager = manager_2.default; +const basic_1 = tslib_1.__importDefault(__webpack_require__(372)); +exports.BasicList = basic_1.default; +const manager_3 = tslib_1.__importDefault(__webpack_require__(248)); +exports.diagnosticManager = manager_3.default; +const ansiparse_1 = __webpack_require__(348); +exports.ansiparse = ansiparse_1.ansiparse; +const watchman_1 = tslib_1.__importDefault(__webpack_require__(230)); +exports.Watchman = watchman_1.default; +const vscode_uri_1 = __webpack_require__(183); +exports.Uri = vscode_uri_1.URI; +const neovim_1 = __webpack_require__(94); +exports.Neovim = neovim_1.Neovim; +exports.Buffer = neovim_1.Buffer; +exports.Window = neovim_1.Window; +const vscode_languageserver_protocol_1 = __webpack_require__(150); +exports.Disposable = vscode_languageserver_protocol_1.Disposable; +exports.Event = vscode_languageserver_protocol_1.Event; +exports.Emitter = vscode_languageserver_protocol_1.Emitter; +tslib_1.__exportStar(__webpack_require__(192), exports); +tslib_1.__exportStar(__webpack_require__(350), exports); +var util_1 = __webpack_require__(177); +exports.disposeAll = util_1.disposeAll; +exports.runCommand = util_1.runCommand; +exports.isRunning = util_1.isRunning; +exports.executable = util_1.executable; +//# sourceMappingURL=index.js.map /***/ }), -/* 325 */ +/* 320 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -class Popup { - constructor(nvim) { - this.nvim = nvim; +const tslib_1 = __webpack_require__(3); +const vscode_languageserver_protocol_1 = __webpack_require__(150); +const commands_1 = tslib_1.__importDefault(__webpack_require__(247)); +const manager_1 = tslib_1.__importDefault(__webpack_require__(248)); +const codeActionmanager_1 = tslib_1.__importDefault(__webpack_require__(321)); +const codeLensManager_1 = tslib_1.__importDefault(__webpack_require__(324)); +const declarationManager_1 = tslib_1.__importDefault(__webpack_require__(325)); +const definitionManager_1 = tslib_1.__importDefault(__webpack_require__(326)); +const documentColorManager_1 = tslib_1.__importDefault(__webpack_require__(327)); +const documentHighlightManager_1 = tslib_1.__importDefault(__webpack_require__(328)); +const documentLinkManager_1 = tslib_1.__importDefault(__webpack_require__(329)); +const documentSymbolManager_1 = tslib_1.__importDefault(__webpack_require__(330)); +const foldingRangeManager_1 = tslib_1.__importDefault(__webpack_require__(331)); +const formatManager_1 = tslib_1.__importDefault(__webpack_require__(332)); +const formatRangeManager_1 = tslib_1.__importDefault(__webpack_require__(333)); +const hoverManager_1 = tslib_1.__importDefault(__webpack_require__(334)); +const implementationManager_1 = tslib_1.__importDefault(__webpack_require__(335)); +const onTypeFormatManager_1 = tslib_1.__importDefault(__webpack_require__(336)); +const rangeManager_1 = tslib_1.__importDefault(__webpack_require__(337)); +const referenceManager_1 = tslib_1.__importDefault(__webpack_require__(338)); +const renameManager_1 = tslib_1.__importDefault(__webpack_require__(339)); +const signatureManager_1 = tslib_1.__importDefault(__webpack_require__(340)); +const typeDefinitionManager_1 = tslib_1.__importDefault(__webpack_require__(341)); +const workspaceSymbolsManager_1 = tslib_1.__importDefault(__webpack_require__(342)); +const manager_2 = tslib_1.__importDefault(__webpack_require__(250)); +const sources_1 = tslib_1.__importDefault(__webpack_require__(254)); +const types_1 = __webpack_require__(192); +const util_1 = __webpack_require__(177); +const complete = tslib_1.__importStar(__webpack_require__(343)); +const position_1 = __webpack_require__(216); +const string_1 = __webpack_require__(213); +const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); +const logger = __webpack_require__(2)('languages'); +function fixDocumentation(str) { + return str.replace(/ /g, ' '); +} +function check(_target, key, descriptor) { + let fn = descriptor.value; + if (typeof fn !== 'function') { + return; } - async create(text, options) { - let { nvim } = this; - this.id = await nvim.call('popup_create', [text, options]); - this.bufferId = await nvim.call('winbufnr', [this.id]); + descriptor.value = function (...args) { + let { cancelTokenSource } = this; + this.cancelTokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource(); + return new Promise((resolve, reject) => { + let resolved = false; + let timer = setTimeout(() => { + cancelTokenSource.cancel(); + logger.error(`${key} timeout after 5s`); + if (!resolved) + reject(new Error(`${key} timeout after 5s`)); + }, 5000); + Promise.resolve(fn.apply(this, args)).then(res => { + clearTimeout(timer); + resolve(res); + }, e => { + clearTimeout(timer); + reject(e); + }); + }); + }; +} +exports.check = check; +class Languages { + constructor() { + this.onTypeFormatManager = new onTypeFormatManager_1.default(); + this.documentLinkManager = new documentLinkManager_1.default(); + this.documentColorManager = new documentColorManager_1.default(); + this.foldingRangeManager = new foldingRangeManager_1.default(); + this.renameManager = new renameManager_1.default(); + this.formatManager = new formatManager_1.default(); + this.codeActionManager = new codeActionmanager_1.default(); + this.workspaceSymbolsManager = new workspaceSymbolsManager_1.default(); + this.formatRangeManager = new formatRangeManager_1.default(); + this.hoverManager = new hoverManager_1.default(); + this.signatureManager = new signatureManager_1.default(); + this.documentSymbolManager = new documentSymbolManager_1.default(); + this.documentHighlightManager = new documentHighlightManager_1.default(); + this.definitionManager = new definitionManager_1.default(); + this.declarationManager = new declarationManager_1.default(); + this.typeDefinitionManager = new typeDefinitionManager_1.default(); + this.referenceManager = new referenceManager_1.default(); + this.implementationManager = new implementationManager_1.default(); + this.codeLensManager = new codeLensManager_1.default(); + this.selectionRangeManager = new rangeManager_1.default(); + this.cancelTokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource(); + workspace_1.default.onWillSaveUntil(event => { + let { languageId } = event.document; + let config = workspace_1.default.getConfiguration('coc.preferences', event.document.uri); + let filetypes = config.get('formatOnSaveFiletypes', []); + if (filetypes.indexOf(languageId) !== -1 || filetypes.some(item => item === '*')) { + let willSaveWaitUntil = async () => { + let options = await workspace_1.default.getFormatOptions(event.document.uri); + let textEdits = await this.provideDocumentFormattingEdits(event.document, options); + return textEdits; + }; + event.waitUntil(willSaveWaitUntil()); + } + }, null, 'languageserver'); + workspace_1.default.ready.then(() => { + this.loadCompleteConfig(); + }, _e => { + // noop + }); + workspace_1.default.onDidChangeConfiguration(this.loadCompleteConfig, this); } - hide() { - if (!this.id) - return; - this.nvim.call('popup_hide', [this.id], true); + get nvim() { + return workspace_1.default.nvim; } - async valid() { - if (!this.bufferId) - return false; - await this.nvim.call('bufexists', [this.bufferId]); + loadCompleteConfig() { + let config = workspace_1.default.getConfiguration('coc.preferences'); + let suggest = workspace_1.default.getConfiguration('suggest'); + function getConfig(key, defaultValue) { + return config.get(key, suggest.get(key, defaultValue)); + } + let labels = suggest.get('completionItemKindLabels', {}); + this.completionItemKindMap = new Map([ + [vscode_languageserver_protocol_1.CompletionItemKind.Text, labels['text'] || 'v'], + [vscode_languageserver_protocol_1.CompletionItemKind.Method, labels['method'] || 'f'], + [vscode_languageserver_protocol_1.CompletionItemKind.Function, labels['function'] || 'f'], + [vscode_languageserver_protocol_1.CompletionItemKind.Constructor, typeof labels['constructor'] == 'function' ? 'f' : labels['con' + 'structor']], + [vscode_languageserver_protocol_1.CompletionItemKind.Field, labels['field'] || 'm'], + [vscode_languageserver_protocol_1.CompletionItemKind.Variable, labels['variable'] || 'v'], + [vscode_languageserver_protocol_1.CompletionItemKind.Class, labels['class'] || 'C'], + [vscode_languageserver_protocol_1.CompletionItemKind.Interface, labels['interface'] || 'I'], + [vscode_languageserver_protocol_1.CompletionItemKind.Module, labels['module'] || 'M'], + [vscode_languageserver_protocol_1.CompletionItemKind.Property, labels['property'] || 'm'], + [vscode_languageserver_protocol_1.CompletionItemKind.Unit, labels['unit'] || 'U'], + [vscode_languageserver_protocol_1.CompletionItemKind.Value, labels['value'] || 'v'], + [vscode_languageserver_protocol_1.CompletionItemKind.Enum, labels['enum'] || 'E'], + [vscode_languageserver_protocol_1.CompletionItemKind.Keyword, labels['keyword'] || 'k'], + [vscode_languageserver_protocol_1.CompletionItemKind.Snippet, labels['snippet'] || 'S'], + [vscode_languageserver_protocol_1.CompletionItemKind.Color, labels['color'] || 'v'], + [vscode_languageserver_protocol_1.CompletionItemKind.File, labels['file'] || 'F'], + [vscode_languageserver_protocol_1.CompletionItemKind.Reference, labels['reference'] || 'r'], + [vscode_languageserver_protocol_1.CompletionItemKind.Folder, labels['folder'] || 'F'], + [vscode_languageserver_protocol_1.CompletionItemKind.EnumMember, labels['enumMember'] || 'm'], + [vscode_languageserver_protocol_1.CompletionItemKind.Constant, labels['constant'] || 'v'], + [vscode_languageserver_protocol_1.CompletionItemKind.Struct, labels['struct'] || 'S'], + [vscode_languageserver_protocol_1.CompletionItemKind.Event, labels['event'] || 'E'], + [vscode_languageserver_protocol_1.CompletionItemKind.Operator, labels['operator'] || 'O'], + [vscode_languageserver_protocol_1.CompletionItemKind.TypeParameter, labels['typeParameter'] || 'T'], + ]); + this.completeConfig = { + defaultKindText: labels['default'] || '', + priority: getConfig('languageSourcePriority', 99), + echodocSupport: getConfig('echodocSupport', false), + waitTime: getConfig('triggerCompletionWait', 60), + detailField: getConfig('detailField', 'abbr'), + detailMaxLength: getConfig('detailMaxLength', 50), + invalidInsertCharacters: getConfig('invalidInsertCharacters', [' ', '(', '<', '{', '[', '\r', '\n']), + }; } - async visible() { - if (!this.id) - return false; - let opt = await this.nvim.call('popup_getpos', [this.id]); - return opt && opt.visible == 1; + registerOnTypeFormattingEditProvider(selector, provider, triggerCharacters) { + return this.onTypeFormatManager.register(selector, provider, triggerCharacters); + } + registerCompletionItemProvider(name, shortcut, languageIds, provider, triggerCharacters = [], allCommitCharacters = [], priority) { + languageIds = typeof languageIds == 'string' ? [languageIds] : languageIds; + let source = this.createCompleteSource(name, shortcut, provider, languageIds, triggerCharacters, allCommitCharacters, priority); + sources_1.default.addSource(source); + logger.debug('created service source', name); + return { + dispose: () => { + sources_1.default.removeSource(source); + } + }; + } + registerCodeActionProvider(selector, provider, clientId, codeActionKinds) { + return this.codeActionManager.register(selector, provider, clientId, codeActionKinds); + } + registerHoverProvider(selector, provider) { + return this.hoverManager.register(selector, provider); + } + registerSelectionRangeProvider(selector, provider) { + return this.selectionRangeManager.register(selector, provider); + } + registerSignatureHelpProvider(selector, provider, triggerCharacters) { + return this.signatureManager.register(selector, provider, triggerCharacters); + } + registerDocumentSymbolProvider(selector, provider) { + return this.documentSymbolManager.register(selector, provider); + } + registerFoldingRangeProvider(selector, provider) { + return this.foldingRangeManager.register(selector, provider); + } + registerDocumentHighlightProvider(selector, provider) { + return this.documentHighlightManager.register(selector, provider); + } + registerCodeLensProvider(selector, provider) { + return this.codeLensManager.register(selector, provider); + } + registerDocumentLinkProvider(selector, provider) { + return this.documentLinkManager.register(selector, provider); + } + registerDocumentColorProvider(selector, provider) { + return this.documentColorManager.register(selector, provider); + } + registerDefinitionProvider(selector, provider) { + return this.definitionManager.register(selector, provider); + } + registerDeclarationProvider(selector, provider) { + return this.declarationManager.register(selector, provider); + } + registerTypeDefinitionProvider(selector, provider) { + return this.typeDefinitionManager.register(selector, provider); + } + registerImplementationProvider(selector, provider) { + return this.implementationManager.register(selector, provider); + } + registerReferencesProvider(selector, provider) { + return this.referenceManager.register(selector, provider); + } + registerRenameProvider(selector, provider) { + return this.renameManager.register(selector, provider); + } + registerWorkspaceSymbolProvider(selector, provider) { + return this.workspaceSymbolsManager.register(selector, provider); + } + registerDocumentFormatProvider(selector, provider, priority = 0) { + return this.formatManager.register(selector, provider, priority); } - show() { - if (!this.id) - return; - this.nvim.call('popup_show', [this.id], true); + registerDocumentRangeFormatProvider(selector, provider, priority = 0) { + return this.formatRangeManager.register(selector, provider, priority); } - move(options) { - if (!this.id) - return; - this.nvim.call('popup_move', [this.id, options], true); + shouldTriggerSignatureHelp(document, triggerCharacter) { + return this.signatureManager.shouldTrigger(document, triggerCharacter); } - async getPosition() { - return await this.nvim.call('popup_getpos', [this.id]); + async getHover(document, position) { + return await this.hoverManager.provideHover(document, position, this.token); } - setFiletype(filetype) { - if (!this.id) - return; - let { nvim } = this; - // nvim.call('win_execute', [this.id, 'syntax enable'], true) - nvim.call('setbufvar', [this.bufferId, '&filetype', filetype], true); + async getSignatureHelp(document, position, token) { + return await this.signatureManager.provideSignatureHelp(document, position, token); } - dispose() { - if (this.id) { - this.nvim.call('popup_close', [this.id], true); - } + async getDefinition(document, position) { + if (!this.definitionManager.hasProvider(document)) + return null; + return await this.definitionManager.provideDefinition(document, position, this.token); } -} -exports.Popup = Popup; -async function createPopup(nvim, text, options) { - let popup = new Popup(nvim); - await popup.create(text, options); - return popup; -} -exports.default = createPopup; -//# sourceMappingURL=popup.js.map - -/***/ }), -/* 326 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const tslib_1 = __webpack_require__(3); -const vscode_languageserver_protocol_1 = __webpack_require__(150); -const callSequence_1 = tslib_1.__importDefault(__webpack_require__(327)); -const object_1 = __webpack_require__(193); -const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const util_1 = __webpack_require__(328); -const logger = __webpack_require__(2)('diagnostic-buffer'); -const severityNames = ['CocError', 'CocWarning', 'CocInfo', 'CocHint']; -// maintains sign and highlightId -class DiagnosticBuffer { - constructor(bufnr, config) { - this.config = config; - this.signIds = new Set(); - this.sequence = null; - this._onDidRefresh = new vscode_languageserver_protocol_1.Emitter(); - this.matchIds = new Set(); - this.diagnostics = []; - this.onDidRefresh = this._onDidRefresh.event; - this.bufnr = bufnr; - this.srdId = workspace_1.default.createNameSpace('coc-diagnostic'); - let timer = null; - let time = Date.now(); - this.refresh = (diagnostics) => { - time = Date.now(); - if (timer) - clearTimeout(timer); - timer = setTimeout(async () => { - let current = time; - if (this.sequence) { - await this.sequence.cancel(); - } - // staled - if (current != time || !this.document) - return; - diagnostics.forEach(o => { - o.range = this.fixRange(o.range); - }); - this._refresh(diagnostics); - }, 30); - }; + async getDeclaration(document, position) { + if (!this.declarationManager.hasProvider(document)) + return null; + return await this.declarationManager.provideDeclaration(document, position, this.token); } - _refresh(diagnostics) { - if (object_1.equals(this.diagnostics, diagnostics)) - return; - let { nvim } = this; - let sequence = this.sequence = new callSequence_1.default(); - let winid; - let bufnr; - sequence.addFunction(async () => { - let arr = await nvim.eval(`[coc#util#valid_state(), bufwinid(${this.bufnr}), bufnr("%")]`); - if (arr[0] == 0 || !this.document) - return true; - winid = arr[1]; - bufnr = arr[2]; - }); - sequence.addFunction(async () => { - nvim.pauseNotification(); - this.setDiagnosticInfo(bufnr, diagnostics); - this.addSigns(diagnostics); - this.setLocationlist(diagnostics, winid); - this.addHighlight(diagnostics, winid); - this.addDiagnosticVText(diagnostics); - let [, err] = await this.nvim.resumeNotification(); - if (err) - logger.error('Diagnostic error:', err); - }); - sequence.start().then(async (canceled) => { - if (!canceled) { - this.diagnostics = diagnostics; - this._onDidRefresh.fire(void 0); - } - }, e => { - logger.error(e); - }); + async getTypeDefinition(document, position) { + if (!this.typeDefinitionManager.hasProvider(document)) + return null; + return await this.typeDefinitionManager.provideTypeDefinition(document, position, this.token); } - setLocationlist(diagnostics, winid) { - if (!this.config.locationlist) - return; - let { nvim, bufnr } = this; - // not shown - if (winid == -1) - return; - let items = []; - for (let diagnostic of diagnostics) { - let item = util_1.getLocationListItem(diagnostic.source, bufnr, diagnostic); - items.push(item); - } - nvim.call('setloclist', [winid, [], ' ', { title: 'Diagnostics of coc', items }], true); + async getImplementation(document, position) { + if (!this.implementationManager.hasProvider(document)) + return null; + return await this.implementationManager.provideReferences(document, position, this.token); } - clearSigns() { - let { nvim, signIds, bufnr } = this; - if (signIds.size > 0) { - nvim.call('coc#util#unplace_signs', [bufnr, Array.from(signIds)], true); - signIds.clear(); - } + async getReferences(document, context, position) { + if (!this.referenceManager.hasProvider(document)) + return null; + return await this.referenceManager.provideReferences(document, position, context, this.token); } - async checkSigns() { - let { nvim, bufnr, signIds } = this; - try { - let content = await this.nvim.call('execute', [`sign place buffer=${bufnr}`]); - let lines = content.split('\n'); - let ids = []; - for (let line of lines) { - let ms = line.match(/^\s*line=\d+\s+id=(\d+)\s+name=(\w+)/); - if (!ms) - continue; - let [, id, name] = ms; - if (!signIds.has(Number(id)) && severityNames.indexOf(name) != -1) { - ids.push(id); - } - } - await nvim.call('coc#util#unplace_signs', [bufnr, ids]); - } - catch (e) { - // noop - } + async getDocumentSymbol(document) { + return await this.documentSymbolManager.provideDocumentSymbols(document, this.token); } - addSigns(diagnostics) { - if (!this.config.enableSign && !this.config.enableHighlightLineNumber) - return; - this.clearSigns(); - let { nvim, bufnr, signIds } = this; - let signId = this.config.signOffset; - signIds.clear(); - let lines = new Set(); - for (let diagnostic of diagnostics) { - let { range, severity } = diagnostic; - let line = range.start.line; - if (lines.has(line)) - continue; - lines.add(line); - let name = util_1.getNameFromSeverity(severity); - nvim.command(`sign place ${signId} line=${line + 1} name=${name} buffer=${bufnr}`, true); - signIds.add(signId); - signId = signId + 1; - } + async getSelectionRanges(document, positions) { + return await this.selectionRangeManager.provideSelectionRanges(document, positions, this.token); } - setDiagnosticInfo(bufnr, diagnostics) { - let lnums = [0, 0, 0, 0]; - let info = { error: 0, warning: 0, information: 0, hint: 0, lnums }; - for (let diagnostic of diagnostics) { - switch (diagnostic.severity) { - case vscode_languageserver_protocol_1.DiagnosticSeverity.Warning: - info.warning = info.warning + 1; - lnums[1] = lnums[1] || diagnostic.range.start.line + 1; - break; - case vscode_languageserver_protocol_1.DiagnosticSeverity.Information: - info.information = info.information + 1; - lnums[2] = lnums[2] || diagnostic.range.start.line + 1; - break; - case vscode_languageserver_protocol_1.DiagnosticSeverity.Hint: - info.hint = info.hint + 1; - lnums[3] = lnums[3] || diagnostic.range.start.line + 1; - break; - default: - lnums[0] = lnums[0] || diagnostic.range.start.line + 1; - info.error = info.error + 1; - } - } - this.nvim.call('coc#util#set_buf_var', [this.bufnr, 'coc_diagnostic_info', info], true); - if (bufnr == this.bufnr) { - this.nvim.call('coc#util#do_autocmd', ['CocDiagnosticChange'], true); - } + async getWorkspaceSymbols(document, query) { + query = query || ''; + return await this.workspaceSymbolsManager.provideWorkspaceSymbols(document, query, this.token); } - addDiagnosticVText(diagnostics) { - let { bufnr, nvim } = this; - if (!this.config.virtualText) - return; - if (!nvim.hasFunction('nvim_buf_set_virtual_text')) - return; - let buffer = this.nvim.createBuffer(bufnr); - let lines = new Set(); - let srcId = this.config.virtualTextSrcId; - let prefix = this.config.virtualTextPrefix; - buffer.clearNamespace(srcId); - for (let diagnostic of diagnostics) { - let { line } = diagnostic.range.start; - if (lines.has(line)) - continue; - lines.add(line); - let highlight = util_1.getNameFromSeverity(diagnostic.severity) + 'VirtualText'; - let msg = diagnostic.message.split(/\n/) - .map((l) => l.trim()) - .filter((l) => l.length > 0) - .slice(0, this.config.virtualTextLines) - .join(this.config.virtualTextLineSeparator); - buffer.setVirtualText(srcId, line, [[prefix + msg, highlight]], {}).logError(); - } + async resolveWorkspaceSymbol(symbol) { + return await this.workspaceSymbolsManager.resolveWorkspaceSymbol(symbol, this.token); } - clearHighlight() { - let { matchIds } = this; - if (!this.document) - return; - this.document.clearMatchIds(matchIds); - this.matchIds.clear(); + async provideRenameEdits(document, position, newName) { + return await this.renameManager.provideRenameEdits(document, position, newName, this.token); } - addHighlight(diagnostics, winid) { - this.clearHighlight(); - if (diagnostics.length == 0) - return; - if (winid == -1 && workspace_1.default.isVim && !workspace_1.default.env.textprop) - return; - const highlights = new Map(); - for (let diagnostic of diagnostics) { - let { range, severity } = diagnostic; - let hlGroup = util_1.getNameFromSeverity(severity) + 'Highlight'; - let ranges = highlights.get(hlGroup) || []; - ranges.push(range); - highlights.set(hlGroup, ranges); - } - for (let [hlGroup, ranges] of highlights.entries()) { - let matchIds = this.document.highlightRanges(ranges, hlGroup, this.srdId); - for (let id of matchIds) - this.matchIds.add(id); + async prepareRename(document, position) { + return await this.renameManager.prepareRename(document, position, this.token); + } + async provideDocumentFormattingEdits(document, options) { + if (!this.formatManager.hasProvider(document)) { + let hasRangeFormater = this.formatRangeManager.hasProvider(document); + if (!hasRangeFormater) { + logger.error('Format provider not found for current document', 'error'); + return null; + } + let end = document.positionAt(document.getText().length); + let range = vscode_languageserver_protocol_1.Range.create(vscode_languageserver_protocol_1.Position.create(0, 0), end); + return await this.provideDocumentRangeFormattingEdits(document, range, options); } + return await this.formatManager.provideDocumentFormattingEdits(document, options, this.token); } - // fix range out of total characters - fixRange(range) { - let { start, end } = range; - if (start.line != end.line) - return range; - let line = this.document.getline(start.line); - if (!line) - return range; - if (start.character < line.length) - return range; - return vscode_languageserver_protocol_1.Range.create(start.line, line.length - 1, start.line, line.length); + async provideDocumentRangeFormattingEdits(document, range, options) { + if (!this.formatRangeManager.hasProvider(document)) + return null; + return await this.formatRangeManager.provideDocumentRangeFormattingEdits(document, range, options, this.token); } /** - * Used on buffer unload + * Get CodeAction list for current document * * @public - * @returns {Promise} + * @param {TextDocument} document + * @param {Range} range + * @param {CodeActionContext} context + * @returns {Promise} */ - async clear() { - if (this.sequence) - this.sequence.cancel().logError(); - let { nvim } = this; - nvim.pauseNotification(); - this.clearHighlight(); - this.clearSigns(); - if (this.config.virtualText - && nvim.hasFunction('nvim_buf_set_virtual_text') - && this.document) { - this.document.buffer.clearNamespace(this.config.virtualTextSrcId); + async getCodeActions(document, range, context, silent = false) { + if (!silent && !this.codeActionManager.hasProvider(document)) { + return null; } - this.setDiagnosticInfo(workspace_1.default.bufnr, []); - await nvim.resumeNotification(false, true); + return await this.codeActionManager.provideCodeActions(document, range, context, this.token); } - dispose() { - if (this.sequence) { - this.sequence.cancel().logError(); - } - this._onDidRefresh.dispose(); + async getDocumentHighLight(document, position) { + return await this.documentHighlightManager.provideDocumentHighlights(document, position, this.token); } - get document() { - if (!this.bufnr) + async getDocumentLinks(document) { + if (!this.documentLinkManager.hasProvider(document)) { return null; - return workspace_1.default.getDocument(this.bufnr); + } + return (await this.documentLinkManager.provideDocumentLinks(document, this.token)) || []; } - get uri() { - if (!this.document) + async resolveDocumentLink(link) { + return await this.documentLinkManager.resolveDocumentLink(link, this.token); + } + async provideDocumentColors(document) { + return await this.documentColorManager.provideDocumentColors(document, this.token); + } + async provideFoldingRanges(document, context) { + if (!this.formatRangeManager.hasProvider(document)) { return null; - return this.document.uri; + } + return await this.foldingRangeManager.provideFoldingRanges(document, context, this.token); } - get nvim() { - return workspace_1.default.nvim; + async provideColorPresentations(color, document) { + return await this.documentColorManager.provideColorPresentations(color, document, this.token); } -} -exports.DiagnosticBuffer = DiagnosticBuffer; -//# sourceMappingURL=buffer.js.map - -/***/ }), -/* 327 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -class CallSequence { - constructor() { - this.funcs = new Set(); - this._canceled = false; - this._resolved = false; + async getCodeLens(document) { + return await this.codeLensManager.provideCodeLenses(document, this.token); } - addFunction(fn) { - this.funcs.add(fn); + async resolveCodeLens(codeLens) { + return await this.codeLensManager.resolveCodeLens(codeLens, this.token); } - start() { - this.promise = new Promise(async (resolve, reject) => { - for (let fn of this.funcs) { - if (this._canceled) - return resolve(true); + async provideDocumentOnTypeEdits(character, document, position) { + return this.onTypeFormatManager.onCharacterType(character, document, position, this.token); + } + hasOnTypeProvider(character, document) { + return this.onTypeFormatManager.getProvider(document, character) != null; + } + hasProvider(id, document) { + switch (id) { + case 'rename': + return this.renameManager.hasProvider(document); + case 'onTypeEdit': + return this.onTypeFormatManager.hasProvider(document); + case 'documentLink': + return this.documentLinkManager.hasProvider(document); + case 'documentColor': + return this.documentColorManager.hasProvider(document); + case 'foldingRange': + return this.foldingRangeManager.hasProvider(document); + case 'format': + return this.formatManager.hasProvider(document); + case 'codeAction': + return this.codeActionManager.hasProvider(document); + case 'workspaceSymbols': + return this.workspaceSymbolsManager.hasProvider(document); + case 'formatRange': + return this.formatRangeManager.hasProvider(document); + case 'hover': + return this.hoverManager.hasProvider(document); + case 'signature': + return this.signatureManager.hasProvider(document); + case 'documentSymbol': + return this.documentSymbolManager.hasProvider(document); + case 'documentHighlight': + return this.documentHighlightManager.hasProvider(document); + case 'definition': + return this.definitionManager.hasProvider(document); + case 'declaration': + return this.declarationManager.hasProvider(document); + case 'typeDefinition': + return this.typeDefinitionManager.hasProvider(document); + case 'reference': + return this.referenceManager.hasProvider(document); + case 'implementation': + return this.implementationManager.hasProvider(document); + case 'codeLens': + return this.codeLensManager.hasProvider(document); + case 'selectionRange': + return this.selectionRangeManager.hasProvider(document); + default: + throw new Error(`${id} not supported.`); + } + } + dispose() { + // noop + } + createDiagnosticCollection(owner) { + return manager_1.default.create(owner); + } + createCompleteSource(name, shortcut, provider, languageIds, triggerCharacters, allCommitCharacters, priority) { + // track them for resolve + let completeItems = []; + // line used for TextEdit + let hasResolve = typeof provider.resolveCompletionItem === 'function'; + priority = priority == null ? this.completeConfig.priority : priority; + // index set of resolved items + let resolvedIndexes = new Set(); + let waitTime = Math.min(Math.max(50, this.completeConfig.waitTime), 300); + let source = { + name, + priority, + shortcut, + enable: true, + sourceType: types_1.SourceType.Service, + filetypes: languageIds, + triggerCharacters: triggerCharacters || [], + doComplete: async (opt, token) => { + let { triggerCharacter, bufnr } = opt; + resolvedIndexes = new Set(); + let isTrigger = triggerCharacters && triggerCharacters.indexOf(triggerCharacter) != -1; + let triggerKind = vscode_languageserver_protocol_1.CompletionTriggerKind.Invoked; + if (opt.triggerForInComplete) { + triggerKind = vscode_languageserver_protocol_1.CompletionTriggerKind.TriggerForIncompleteCompletions; + } + else if (isTrigger) { + triggerKind = vscode_languageserver_protocol_1.CompletionTriggerKind.TriggerCharacter; + } + if (opt.triggerCharacter) + await util_1.wait(waitTime); + if (token.isCancellationRequested) + return null; + let position = complete.getPosition(opt); + let context = { triggerKind, option: opt }; + if (isTrigger) + context.triggerCharacter = triggerCharacter; + let result; + try { + let doc = workspace_1.default.getDocument(bufnr); + result = await Promise.resolve(provider.provideCompletionItems(doc.textDocument, position, token, context)); + } + catch (e) { + // don't disturb user + logger.error(`Source "${name}" complete error:`, e); + return null; + } + if (!result || token.isCancellationRequested) + return null; + completeItems = Array.isArray(result) ? result : result.items; + if (!completeItems || completeItems.length == 0) + return null; + // used for fixed col + let option = Object.assign({}, opt); + if (typeof result.startcol == 'number') { + option.col = result.startcol; + } + let items = completeItems.map((o, index) => { + let item = this.convertVimCompleteItem(o, shortcut, option); + item.index = index; + return item; + }); + return { + startcol: result.startcol, + isIncomplete: !!result.isIncomplete, + items + }; + }, + onCompleteResolve: async (item, token) => { + let resolving = completeItems[item.index]; + if (!resolving) + return; + if (hasResolve && !resolvedIndexes.has(item.index)) { + let resolved = await Promise.resolve(provider.resolveCompletionItem(resolving, token)); + if (token.isCancellationRequested) + return; + resolvedIndexes.add(item.index); + if (resolved) + Object.assign(resolving, resolved); + } + if (item.documentation == null) { + let { documentation, detail } = resolving; + if (!documentation && !detail) + return; + let docs = []; + if (detail && !item.detailShown && detail != item.word) { + detail = detail.replace(/\n\s*/g, ' '); + if (detail.length) { + let isText = /^[\w-\s.,\t]+$/.test(detail); + let filetype = isText ? 'txt' : await workspace_1.default.nvim.eval('&filetype'); + docs.push({ filetype: isText ? 'txt' : filetype, content: detail }); + } + } + if (documentation) { + if (typeof documentation == 'string') { + docs.push({ + filetype: 'markdown', + content: fixDocumentation(documentation) + }); + } + else if (documentation.value) { + docs.push({ + filetype: documentation.kind == 'markdown' ? 'markdown' : 'txt', + content: fixDocumentation(documentation.value) + }); + } + } + item.documentation = docs; + } + }, + onCompleteDone: async (vimItem, opt) => { + let item = completeItems[vimItem.index]; + if (!item) + return; + let line = opt.linenr - 1; + // tslint:disable-next-line: deprecation + if (item.insertText && !item.textEdit) { + item.textEdit = { + range: vscode_languageserver_protocol_1.Range.create(line, opt.col, line, opt.colnr - 1), + // tslint:disable-next-line: deprecation + newText: item.insertText + }; + } + if (vimItem.line) + Object.assign(opt, { line: vimItem.line }); try { - let cancel = await Promise.resolve(fn()); - if (cancel === true) { - this._canceled = true; - return resolve(true); + let isSnippet = await this.applyTextEdit(item, opt); + if (isSnippet && manager_2.default.isPlainText(item.textEdit.newText)) { + isSnippet = false; + } + let { additionalTextEdits } = item; + if (additionalTextEdits && item.textEdit) { + let r = item.textEdit.range; + additionalTextEdits = additionalTextEdits.filter(edit => { + if (position_1.rangeOverlap(r, edit.range)) { + logger.error('Filtered overlap additionalTextEdit:', edit); + return false; + } + return true; + }); } + await this.applyAdditionalEdits(additionalTextEdits, opt.bufnr, isSnippet); + if (isSnippet) + await manager_2.default.selectCurrentPlaceholder(); + if (item.command) + commands_1.default.execute(item.command); } catch (e) { - reject(e); - return; + logger.error('Error on CompleteDone:', e); } + }, + shouldCommit: (item, character) => { + let completeItem = completeItems[item.index]; + if (!completeItem) + return false; + let commitCharacters = completeItem.commitCharacters || allCommitCharacters; + return commitCharacters.indexOf(character) !== -1; } - this._resolved = true; - resolve(false); - }); - return this.promise; - } - ready() { - return this.promise; - } - cancel() { - if (this._resolved) - return Promise.resolve(void 0); - if (this._canceled) - return this.promise; - this._canceled = true; - return this.promise; - } -} -exports.default = CallSequence; -//# sourceMappingURL=callSequence.js.map - -/***/ }), -/* 328 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const vscode_languageserver_protocol_1 = __webpack_require__(150); -function getSeverityName(severity) { - switch (severity) { - case vscode_languageserver_protocol_1.DiagnosticSeverity.Error: - return 'Error'; - case vscode_languageserver_protocol_1.DiagnosticSeverity.Warning: - return 'Warning'; - case vscode_languageserver_protocol_1.DiagnosticSeverity.Information: - return 'Information'; - case vscode_languageserver_protocol_1.DiagnosticSeverity.Hint: - return 'Hint'; - default: - return 'Error'; - } -} -exports.getSeverityName = getSeverityName; -function getSeverityType(severity) { - switch (severity) { - case vscode_languageserver_protocol_1.DiagnosticSeverity.Error: - return 'E'; - case vscode_languageserver_protocol_1.DiagnosticSeverity.Warning: - return 'W'; - case vscode_languageserver_protocol_1.DiagnosticSeverity.Information: - return 'I'; - case vscode_languageserver_protocol_1.DiagnosticSeverity.Hint: - return 'I'; - default: - return 'Error'; + }; + return source; } -} -exports.getSeverityType = getSeverityType; -function severityLevel(level) { - switch (level) { - case 'hint': - return vscode_languageserver_protocol_1.DiagnosticSeverity.Hint; - case 'information': - return vscode_languageserver_protocol_1.DiagnosticSeverity.Information; - case 'warning': - return vscode_languageserver_protocol_1.DiagnosticSeverity.Warning; - case 'error': - return vscode_languageserver_protocol_1.DiagnosticSeverity.Error; - default: - return vscode_languageserver_protocol_1.DiagnosticSeverity.Hint; + get token() { + this.cancelTokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource(); + return this.cancelTokenSource.token; } -} -exports.severityLevel = severityLevel; -function getNameFromSeverity(severity) { - switch (severity) { - case vscode_languageserver_protocol_1.DiagnosticSeverity.Error: - return 'CocError'; - case vscode_languageserver_protocol_1.DiagnosticSeverity.Warning: - return 'CocWarning'; - case vscode_languageserver_protocol_1.DiagnosticSeverity.Information: - return 'CocInfo'; - case vscode_languageserver_protocol_1.DiagnosticSeverity.Hint: - return 'CocHint'; - default: - return 'CocError'; + async applyTextEdit(item, option) { + let { nvim } = this; + let { textEdit } = item; + if (!textEdit) + return false; + let { line, bufnr, linenr } = option; + let doc = workspace_1.default.getDocument(bufnr); + if (!doc) + return false; + let { range, newText } = textEdit; + let isSnippet = item.insertTextFormat === vscode_languageserver_protocol_1.InsertTextFormat.Snippet; + // replace inserted word + let start = line.substr(0, range.start.character); + let end = line.substr(range.end.character); + if (isSnippet) { + await doc.applyEdits(nvim, [{ + range: vscode_languageserver_protocol_1.Range.create(linenr - 1, 0, linenr, 0), + newText: `${start}${end}\n` + }]); + // can't select, since additionalTextEdits would break selection + let pos = vscode_languageserver_protocol_1.Position.create(linenr - 1, range.start.character); + return await manager_2.default.insertSnippet(newText, false, vscode_languageserver_protocol_1.Range.create(pos, pos)); + } + let newLines = `${start}${newText}${end}`.split('\n'); + if (newLines.length == 1) { + await nvim.call('coc#util#setline', [linenr, newLines[0]]); + await workspace_1.default.moveTo(vscode_languageserver_protocol_1.Position.create(linenr - 1, (start + newText).length)); + } + else { + let buffer = nvim.createBuffer(bufnr); + await buffer.setLines(newLines, { + start: linenr - 1, + end: linenr, + strictIndexing: false + }); + let line = linenr - 1 + newLines.length - 1; + let character = newLines[newLines.length - 1].length - end.length; + await workspace_1.default.moveTo({ line, character }); + } + return false; } -} -exports.getNameFromSeverity = getNameFromSeverity; -function getLocationListItem(owner, bufnr, diagnostic) { - let { start } = diagnostic.range; - let msg = diagnostic.message.split('\n')[0]; - let type = getSeverityName(diagnostic.severity).slice(0, 1).toUpperCase(); - return { - bufnr, - lnum: start.line + 1, - col: start.character + 1, - text: `[${owner}${diagnostic.code ? ' ' + diagnostic.code : ''}] ${msg} [${type}]`, - type - }; -} -exports.getLocationListItem = getLocationListItem; -//# sourceMappingURL=util.js.map - -/***/ }), -/* 329 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const vscode_languageserver_protocol_1 = __webpack_require__(150); -const vscode_uri_1 = __webpack_require__(183); -const position_1 = __webpack_require__(216); -const logger = __webpack_require__(2)('diagnostic-collection'); -class Collection { - constructor(owner) { - this.diagnosticsMap = new Map(); - this._onDispose = new vscode_languageserver_protocol_1.Emitter(); - this._onDidDiagnosticsChange = new vscode_languageserver_protocol_1.Emitter(); - this._onDidDiagnosticsClear = new vscode_languageserver_protocol_1.Emitter(); - this.onDispose = this._onDispose.event; - this.onDidDiagnosticsChange = this._onDidDiagnosticsChange.event; - this.onDidDiagnosticsClear = this._onDidDiagnosticsClear.event; - this.name = owner; + async applyAdditionalEdits(textEdits, bufnr, snippet) { + if (!textEdits || textEdits.length == 0) + return; + let document = workspace_1.default.getDocument(bufnr); + if (!document) + return; + await document._fetchContent(); + // how to move cursor after edit + let changed = null; + let pos = await workspace_1.default.getCursorPosition(); + if (!snippet) + changed = position_1.getChangedFromEdits(pos, textEdits); + await document.applyEdits(this.nvim, textEdits); + if (changed) + await workspace_1.default.moveTo(vscode_languageserver_protocol_1.Position.create(pos.line + changed.line, pos.character + changed.character)); } - set(entries, diagnostics) { - if (Array.isArray(entries)) { - let map = new Map(); - for (let item of entries) { - let [file, diagnostics] = item; - let exists = map.get(file) || []; - if (diagnostics != null) { - for (let diagnostic of diagnostics) { - exists.push(diagnostic); - } + convertVimCompleteItem(item, shortcut, opt) { + let { echodocSupport, detailField, detailMaxLength, invalidInsertCharacters } = this.completeConfig; + let hasAdditionalEdit = item.additionalTextEdits && item.additionalTextEdits.length > 0; + let isSnippet = item.insertTextFormat === vscode_languageserver_protocol_1.InsertTextFormat.Snippet || hasAdditionalEdit; + let label = item.label.trim(); + let obj = { + word: complete.getWord(item, opt, invalidInsertCharacters), + abbr: label, + menu: `[${shortcut}]`, + kind: complete.completionKindString(item.kind, this.completionItemKindMap, this.completeConfig.defaultKindText), + sortText: item.sortText || null, + sourceScore: item['score'] || null, + filterText: item.filterText || label, + isSnippet, + dup: item.data && item.data.dup == 0 ? 0 : 1 + }; + if (item && item.detail && detailField != 'preview') { + let detail = item.detail.replace(/\n\s*/g, ' '); + if (string_1.byteLength(detail) < detailMaxLength) { + if (detailField == 'menu') { + obj.menu = `${detail} ${obj.menu}`; } - else { - exists = []; + else if (detailField == 'abbr') { + obj.abbr = `${obj.abbr} - ${detail}`; } - map.set(file, exists); - } - for (let key of map.keys()) { - this.set(key, map.get(key)); + obj.detailShown = 1; } - return; } - let uri = entries; - uri = vscode_uri_1.URI.parse(uri).toString(); - if (diagnostics) { - diagnostics.forEach(o => { - let { range } = o; - range.start = range.start || vscode_languageserver_protocol_1.Position.create(0, 0); - range.end = range.end || vscode_languageserver_protocol_1.Position.create(1, 0); - if (position_1.emptyRange(range)) { - o.range.end = { - line: o.range.end.line, - character: o.range.end.character + 1 - }; - } - o.source = o.source || this.name; - }); + if (item.documentation) { + obj.info = typeof item.documentation == 'string' ? item.documentation : item.documentation.value; } - this.diagnosticsMap.set(uri, diagnostics || []); - this._onDidDiagnosticsChange.fire(uri); - return; - } - delete(uri) { - this.diagnosticsMap.delete(uri); - this._onDidDiagnosticsChange.fire(uri); - } - clear() { - let uris = Array.from(this.diagnosticsMap.keys()); - this.diagnosticsMap.clear(); - this._onDidDiagnosticsClear.fire(uris); - } - forEach(callback, thisArg) { - for (let uri of this.diagnosticsMap.keys()) { - let diagnostics = this.diagnosticsMap.get(uri); - callback.call(thisArg, uri, diagnostics, this); + else { + obj.info = ''; } - } - get(uri) { - let arr = this.diagnosticsMap.get(uri); - return arr == null ? [] : arr; - } - has(uri) { - return this.diagnosticsMap.has(uri); - } - dispose() { - this.clear(); - this._onDispose.fire(void 0); - this._onDispose.dispose(); - this._onDidDiagnosticsClear.dispose(); - this._onDidDiagnosticsChange.dispose(); + if (!obj.word) + obj.empty = 1; + if (item.textEdit) + obj.line = opt.line; + if (item.kind == vscode_languageserver_protocol_1.CompletionItemKind.Folder && !obj.abbr.endsWith('/')) { + obj.abbr = obj.abbr + '/'; + } + if (echodocSupport && item.kind >= 2 && item.kind <= 4) { + let fields = [item.detail || '', obj.abbr, obj.word]; + for (let s of fields) { + if (s.indexOf('(') !== -1) { + obj.signature = s; + break; + } + } + } + if (item.preselect) + obj.preselect = true; + item.data = item.data || {}; + if (item.data.optional) + obj.abbr = obj.abbr + '?'; + return obj; } } -exports.default = Collection; -//# sourceMappingURL=collection.js.map +tslib_1.__decorate([ + check +], Languages.prototype, "getHover", null); +tslib_1.__decorate([ + check +], Languages.prototype, "getDefinition", null); +tslib_1.__decorate([ + check +], Languages.prototype, "getDeclaration", null); +tslib_1.__decorate([ + check +], Languages.prototype, "getTypeDefinition", null); +tslib_1.__decorate([ + check +], Languages.prototype, "getImplementation", null); +tslib_1.__decorate([ + check +], Languages.prototype, "getReferences", null); +tslib_1.__decorate([ + check +], Languages.prototype, "getDocumentSymbol", null); +tslib_1.__decorate([ + check +], Languages.prototype, "getSelectionRanges", null); +tslib_1.__decorate([ + check +], Languages.prototype, "getWorkspaceSymbols", null); +tslib_1.__decorate([ + check +], Languages.prototype, "resolveWorkspaceSymbol", null); +tslib_1.__decorate([ + check +], Languages.prototype, "provideRenameEdits", null); +tslib_1.__decorate([ + check +], Languages.prototype, "prepareRename", null); +tslib_1.__decorate([ + check +], Languages.prototype, "provideDocumentFormattingEdits", null); +tslib_1.__decorate([ + check +], Languages.prototype, "provideDocumentRangeFormattingEdits", null); +tslib_1.__decorate([ + check +], Languages.prototype, "getCodeActions", null); +tslib_1.__decorate([ + check +], Languages.prototype, "getDocumentHighLight", null); +tslib_1.__decorate([ + check +], Languages.prototype, "getDocumentLinks", null); +tslib_1.__decorate([ + check +], Languages.prototype, "resolveDocumentLink", null); +tslib_1.__decorate([ + check +], Languages.prototype, "provideDocumentColors", null); +tslib_1.__decorate([ + check +], Languages.prototype, "provideFoldingRanges", null); +tslib_1.__decorate([ + check +], Languages.prototype, "provideColorPresentations", null); +tslib_1.__decorate([ + check +], Languages.prototype, "getCodeLens", null); +tslib_1.__decorate([ + check +], Languages.prototype, "resolveCodeLens", null); +tslib_1.__decorate([ + check +], Languages.prototype, "provideDocumentOnTypeEdits", null); +exports.default = new Languages(); +//# sourceMappingURL=languages.js.map /***/ }), -/* 330 */ +/* 321 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52544,8 +51464,8 @@ exports.default = Collection; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); const logger = __webpack_require__(2)('codeActionManager'); class CodeActionManager extends manager_1.default { register(selector, provider, clientId, codeActionKinds) { @@ -52610,7 +51530,7 @@ exports.default = CodeActionManager; //# sourceMappingURL=codeActionmanager.js.map /***/ }), -/* 331 */ +/* 322 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52690,7 +51610,42 @@ exports.default = Manager; //# sourceMappingURL=manager.js.map /***/ }), -/* 332 */ +/* 323 */ +/***/ (function(module, exports, __webpack_require__) { + +var rng = __webpack_require__(224); +var bytesToUuid = __webpack_require__(225); + +function v4(options, buf, offset) { + var i = buf && offset || 0; + + if (typeof(options) == 'string') { + buf = options === 'binary' ? new Array(16) : null; + options = null; + } + options = options || {}; + + var rnds = options.random || (options.rng || rng)(); + + // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + rnds[6] = (rnds[6] & 0x0f) | 0x40; + rnds[8] = (rnds[8] & 0x3f) | 0x80; + + // Copy bytes to buffer, if provided + if (buf) { + for (var ii = 0; ii < 16; ++ii) { + buf[i + ii] = rnds[ii]; + } + } + + return buf || bytesToUuid(rnds); +} + +module.exports = v4; + + +/***/ }), +/* 324 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52698,9 +51653,9 @@ exports.default = Manager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); -const lodash_1 = __webpack_require__(315); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); +const lodash_1 = __webpack_require__(317); // const logger = require('../util/logger')('codeActionManager') class CodeLensManager extends manager_1.default { register(selector, provider) { @@ -52754,7 +51709,7 @@ exports.default = CodeLensManager; //# sourceMappingURL=codeLensManager.js.map /***/ }), -/* 333 */ +/* 325 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52762,8 +51717,8 @@ exports.default = CodeLensManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); const logger = __webpack_require__(2)('definitionManager'); class DeclarationManager extends manager_1.default { register(selector, provider) { @@ -52792,7 +51747,7 @@ exports.default = DeclarationManager; //# sourceMappingURL=declarationManager.js.map /***/ }), -/* 334 */ +/* 326 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52800,8 +51755,8 @@ exports.default = DeclarationManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); const logger = __webpack_require__(2)('definitionManager'); class DefinitionManager extends manager_1.default { register(selector, provider) { @@ -52833,7 +51788,7 @@ exports.default = DefinitionManager; //# sourceMappingURL=definitionManager.js.map /***/ }), -/* 335 */ +/* 327 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52841,8 +51796,8 @@ exports.default = DefinitionManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class DocumentColorManager extends manager_1.default { register(selector, provider) { let item = { @@ -52880,7 +51835,7 @@ exports.default = DocumentColorManager; //# sourceMappingURL=documentColorManager.js.map /***/ }), -/* 336 */ +/* 328 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52888,8 +51843,8 @@ exports.default = DocumentColorManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class DocumentHighlightManager extends manager_1.default { register(selector, provider) { let item = { @@ -52917,7 +51872,7 @@ exports.default = DocumentHighlightManager; //# sourceMappingURL=documentHighlightManager.js.map /***/ }), -/* 337 */ +/* 329 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52925,8 +51880,8 @@ exports.default = DocumentHighlightManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class DocumentLinkManager extends manager_1.default { register(selector, provider) { let item = { @@ -52980,7 +51935,7 @@ exports.default = DocumentLinkManager; //# sourceMappingURL=documentLinkManager.js.map /***/ }), -/* 338 */ +/* 330 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52988,8 +51943,8 @@ exports.default = DocumentLinkManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class DocumentSymbolManager extends manager_1.default { register(selector, provider) { let item = { @@ -53017,7 +51972,7 @@ exports.default = DocumentSymbolManager; //# sourceMappingURL=documentSymbolManager.js.map /***/ }), -/* 339 */ +/* 331 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53025,8 +51980,8 @@ exports.default = DocumentSymbolManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class FoldingRangeManager extends manager_1.default { register(selector, provider) { let item = { @@ -53054,7 +52009,7 @@ exports.default = FoldingRangeManager; //# sourceMappingURL=foldingRangeManager.js.map /***/ }), -/* 340 */ +/* 332 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53062,8 +52017,8 @@ exports.default = FoldingRangeManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class FormatManager extends manager_1.default { register(selector, provider, priority = 0) { let item = { @@ -53092,7 +52047,7 @@ exports.default = FormatManager; //# sourceMappingURL=formatManager.js.map /***/ }), -/* 341 */ +/* 333 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53100,8 +52055,8 @@ exports.default = FormatManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class FormatRangeManager extends manager_1.default { register(selector, provider, priority = 0) { let item = { @@ -53130,7 +52085,7 @@ exports.default = FormatRangeManager; //# sourceMappingURL=formatRangeManager.js.map /***/ }), -/* 342 */ +/* 334 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53138,8 +52093,8 @@ exports.default = FormatRangeManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class HoverManager extends manager_1.default { register(selector, provider) { let item = { @@ -53173,7 +52128,7 @@ exports.default = HoverManager; //# sourceMappingURL=hoverManager.js.map /***/ }), -/* 343 */ +/* 335 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53181,8 +52136,8 @@ exports.default = HoverManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class ImplementationManager extends manager_1.default { register(selector, provider) { let item = { @@ -53213,7 +52168,7 @@ exports.default = ImplementationManager; //# sourceMappingURL=implementationManager.js.map /***/ }), -/* 344 */ +/* 336 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53274,7 +52229,7 @@ exports.default = OnTypeFormatManager; //# sourceMappingURL=onTypeFormatManager.js.map /***/ }), -/* 345 */ +/* 337 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53282,8 +52237,8 @@ exports.default = OnTypeFormatManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class SelectionRangeManager extends manager_1.default { register(selector, provider) { let item = { @@ -53311,7 +52266,7 @@ exports.default = SelectionRangeManager; //# sourceMappingURL=rangeManager.js.map /***/ }), -/* 346 */ +/* 338 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53319,8 +52274,8 @@ exports.default = SelectionRangeManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class ReferenceManager extends manager_1.default { register(selector, provider) { let item = { @@ -53351,7 +52306,7 @@ exports.default = ReferenceManager; //# sourceMappingURL=referenceManager.js.map /***/ }), -/* 347 */ +/* 339 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53359,8 +52314,8 @@ exports.default = ReferenceManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class RenameManager extends manager_1.default { register(selector, provider) { let item = { @@ -53401,7 +52356,7 @@ exports.default = RenameManager; //# sourceMappingURL=renameManager.js.map /***/ }), -/* 348 */ +/* 340 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53409,8 +52364,8 @@ exports.default = RenameManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class SignatureManager extends manager_1.default { register(selector, provider, triggerCharacters) { let characters = triggerCharacters.reduce((p, c) => { @@ -53451,7 +52406,7 @@ exports.default = SignatureManager; //# sourceMappingURL=signatureManager.js.map /***/ }), -/* 349 */ +/* 341 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53459,8 +52414,8 @@ exports.default = SignatureManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class TypeDefinitionManager extends manager_1.default { register(selector, provider) { let item = { @@ -53491,7 +52446,7 @@ exports.default = TypeDefinitionManager; //# sourceMappingURL=typeDefinitionManager.js.map /***/ }), -/* 350 */ +/* 342 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53499,8 +52454,8 @@ exports.default = TypeDefinitionManager; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const manager_1 = tslib_1.__importDefault(__webpack_require__(331)); -const uuid = __webpack_require__(324); +const manager_1 = tslib_1.__importDefault(__webpack_require__(322)); +const uuid = __webpack_require__(323); class WorkspaceSymbolManager extends manager_1.default { register(selector, provider) { let item = { @@ -53533,125 +52488,592 @@ class WorkspaceSymbolManager extends manager_1.default { if (typeof provider.resolveWorkspaceSymbol != 'function') { return Promise.resolve(symbolInfo); } - return await Promise.resolve(provider.resolveWorkspaceSymbol(symbolInfo, token)); - } - dispose() { - this.providers = new Set(); + return await Promise.resolve(provider.resolveWorkspaceSymbol(symbolInfo, token)); + } + dispose() { + this.providers = new Set(); + } +} +exports.default = WorkspaceSymbolManager; +//# sourceMappingURL=workspaceSymbolsManager.js.map + +/***/ }), +/* 343 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const vscode_languageserver_types_1 = __webpack_require__(162); +const parser_1 = __webpack_require__(251); +const string_1 = __webpack_require__(213); +// const logger = require('./logger')('util-complete') +function getPosition(opt) { + let { line, linenr, colnr } = opt; + let part = string_1.byteSlice(line, 0, colnr - 1); + return { + line: linenr - 1, + character: part.length + }; +} +exports.getPosition = getPosition; +function getWord(item, opt, invalidInsertCharacters) { + // tslint:disable-next-line: deprecation + let { label, data, insertTextFormat, insertText, textEdit } = item; + let word; + let newText; + if (data && data.word) + return data.word; + if (textEdit) { + let { range } = textEdit; + newText = textEdit.newText; + if (range && range.start.line == range.end.line) { + let { line, col, colnr } = opt; + let character = string_1.characterIndex(line, col); + if (range.start.character > character) { + let before = line.slice(character - range.start.character); + newText = before + newText; + } + else { + let start = line.slice(range.start.character, character); + if (start.length && newText.startsWith(start)) { + newText = newText.slice(start.length); + } + } + character = string_1.characterIndex(line, colnr - 1); + if (range.end.character > character) { + let end = line.slice(character, range.end.character); + if (newText.endsWith(end)) { + newText = newText.slice(0, -end.length); + } + } + } + } + else { + newText = insertText; + } + if (insertTextFormat == vscode_languageserver_types_1.InsertTextFormat.Snippet + && newText + && newText.indexOf('$') !== -1) { + let parser = new parser_1.SnippetParser(); + let snippet = parser.text(newText); + word = snippet ? getValidWord(snippet, invalidInsertCharacters) : label; + } + else { + word = getValidWord(newText, invalidInsertCharacters) || label; + } + return word; +} +exports.getWord = getWord; +function getDocumentation(item) { + let { documentation } = item; + if (!documentation) + return ''; + if (typeof documentation === 'string') + return documentation; + return documentation.value; +} +exports.getDocumentation = getDocumentation; +function completionKindString(kind, map, defaultValue = '') { + return map.get(kind) || defaultValue; +} +exports.completionKindString = completionKindString; +function getSnippetDocumentation(languageId, body) { + languageId = languageId.replace(/react$/, ''); + let str = body.replace(/\$\d+/g, '').replace(/\$\{\d+(?::([^{]+))?\}/, '$1'); + str = '``` ' + languageId + '\n' + str + '\n' + '```'; + return str; +} +exports.getSnippetDocumentation = getSnippetDocumentation; +function getValidWord(text, invalidChars) { + if (!text) + return ''; + for (let i = 0; i < text.length; i++) { + let c = text[i]; + if (invalidChars.indexOf(c) !== -1) { + return text.slice(0, i); + } + } + return text; +} +exports.getValidWord = getValidWord; +//# sourceMappingURL=complete.js.map + +/***/ }), +/* 344 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const tslib_1 = __webpack_require__(3); +const highlight_1 = __webpack_require__(345); +const string_1 = __webpack_require__(213); +const array_1 = __webpack_require__(215); +const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); +const logger = __webpack_require__(2)('model-floatBuffer'); +class FloatBuffer { + constructor(nvim, buffer, window) { + this.nvim = nvim; + this.buffer = buffer; + this.window = window; + this.lines = []; + this.positions = []; + this.enableHighlight = true; + this.highlightTimeout = 500; + this.tabstop = 2; + this.width = 0; + let config = workspace_1.default.getConfiguration('coc.preferences'); + this.enableHighlight = config.get('enableFloatHighlight', true); + this.highlightTimeout = config.get('highlightTimeout', 500); + buffer.getOption('tabstop').then(val => { + this.tabstop = val; + }, _e => { + // noop + }); + } + getHeight(docs, maxWidth) { + let l = 0; + for (let doc of docs) { + let lines = doc.content.split(/\r?\n/); + if (doc.filetype == 'markdown') { + lines = lines.filter(s => !s.startsWith('```')); + } + for (let line of lines) { + l = l + Math.max(1, Math.ceil(string_1.byteLength(line) / (maxWidth - 4))); + } + } + return l + docs.length - 1; + } + get valid() { + return this.buffer.valid; + } + calculateFragments(docs, maxWidth) { + let fragments = []; + let idx = 0; + let currLine = 0; + let newLines = []; + let fill = false; + let positions = this.positions = []; + for (let doc of docs) { + let lines = []; + let content = doc.content.replace(/\s+$/, ''); + let arr = content.split(/\r?\n/); + if (['Error', 'Info', 'Warning', 'Hint'].indexOf(doc.filetype) !== -1) { + fill = true; + } + // let [start, end] = doc.active || [] + for (let str of arr) { + lines.push(str); + if (doc.active) { + let part = str.slice(doc.active[0], doc.active[1]); + positions.push([currLine + 1, doc.active[0] + 1, string_1.byteLength(part)]); + } + } + fragments.push({ + start: currLine, + lines, + filetype: doc.filetype + }); + newLines.push(...lines.filter(s => !/^\s*```/.test(s))); + if (idx != docs.length - 1) { + newLines.push('—'); + currLine = newLines.length; + } + idx = idx + 1; + } + let width = this.width = Math.min(Math.max(...newLines.map(s => this.getWidth(s))) + 2, maxWidth); + this.lines = newLines.map(s => { + if (s == '—') + return '—'.repeat(width - 2); + return s; + }); + return fragments; + } + getWidth(line) { + let { tabstop } = this; + line = line.replace(/\t/g, ' '.repeat(tabstop)); + return string_1.byteLength(line); + } + async setDocuments(docs, maxWidth) { + let fragments = this.calculateFragments(docs, maxWidth); + let filetype = await this.nvim.eval('&filetype'); + if (workspace_1.default.isNvim) { + fragments = fragments.reduce((p, c) => { + p.push(...this.splitFragment(c, filetype)); + return p; + }, []); + } + if (this.enableHighlight) { + let arr = await Promise.all(fragments.map(f => { + return highlight_1.getHiglights(f.lines, f.filetype, this.highlightTimeout).then(highlights => { + return highlights.map(highlight => { + return Object.assign({}, highlight, { line: highlight.line + f.start }); + }); + }); + })); + this.highlights = arr.reduce((p, c) => p.concat(c), []); + } + else { + this.highlights = []; + } + } + splitFragment(fragment, defaultFileType) { + let res = []; + let filetype = fragment.filetype; + let lines = []; + let curr = fragment.start; + let inBlock = false; + for (let line of fragment.lines) { + let ms = line.match(/^\s*```\s*(\w+)?/); + if (ms != null) { + if (lines.length) { + res.push({ lines, filetype: this.fixFiletype(filetype), start: curr - lines.length }); + lines = []; + } + inBlock = !inBlock; + filetype = inBlock ? ms[1] || defaultFileType : fragment.filetype; + } + else { + lines.push(line); + curr = curr + 1; + } + } + if (lines.length) { + res.push({ lines, filetype: this.fixFiletype(filetype), start: curr - lines.length }); + lines = []; + } + return res; + } + fixFiletype(filetype) { + if (filetype == 'ts') + return 'typescript'; + if (filetype == 'js') + return 'javascript'; + if (filetype == 'bash') + return 'sh'; + return filetype; + } + setLines() { + let { buffer, lines, nvim, highlights } = this; + nvim.call('clearmatches', this.window ? [this.window.id] : [], true); + buffer.clearNamespace(-1, 0, -1); + buffer.setLines(lines, { start: 0, end: -1, strictIndexing: false }, true); + if (highlights.length) { + let positions = []; + for (let highlight of highlights) { + buffer.addHighlight(Object.assign({ srcId: workspace_1.default.createNameSpace('coc-float') }, highlight)).catch(_e => { + // noop + }); + if (highlight.isMarkdown) { + let line = lines[highlight.line]; + if (line) { + let before = line[string_1.characterIndex(line, highlight.colStart)]; + let after = line[string_1.characterIndex(line, highlight.colEnd) - 1]; + if (before == after && ['_', '`', '*'].indexOf(before) !== -1) { + positions.push([highlight.line + 1, highlight.colStart + 1]); + positions.push([highlight.line + 1, highlight.colEnd]); + } + if (highlight.colEnd - highlight.colStart == 2 && before == '\\') { + positions.push([highlight.line + 1, highlight.colStart + 1]); + } + } + } + } + for (let arr of array_1.group(positions, 8)) { + if (this.window) { + nvim.call('win_execute', [this.window.id, `call matchaddpos('Conceal', ${JSON.stringify(arr)},11)`], true); + } + else { + nvim.call('matchaddpos', ['Conceal', arr, 11], true); + } + } + } + for (let arr of array_1.group(this.positions || [], 8)) { + arr = arr.filter(o => o[2] != 0); + if (arr.length) { + if (this.window) { + nvim.call('win_execute', [this.window.id, `call matchaddpos('CocUnderline', ${JSON.stringify(arr)},12)`], true); + } + else { + nvim.call('matchaddpos', ['CocUnderline', arr, 12], true); + } + } + } } } -exports.default = WorkspaceSymbolManager; -//# sourceMappingURL=workspaceSymbolsManager.js.map +exports.default = FloatBuffer; +//# sourceMappingURL=floatBuffer.js.map /***/ }), -/* 351 */ +/* 345 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const vscode_languageserver_types_1 = __webpack_require__(162); -const parser_1 = __webpack_require__(249); +const tslib_1 = __webpack_require__(3); +const neovim_1 = __webpack_require__(94); +const cp = tslib_1.__importStar(__webpack_require__(178)); +const crypto_1 = __webpack_require__(160); +const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); +const path_1 = tslib_1.__importDefault(__webpack_require__(20)); +const lodash_1 = __webpack_require__(317); +const os_1 = tslib_1.__importDefault(__webpack_require__(14)); +const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); const string_1 = __webpack_require__(213); -// const logger = require('./logger')('util-complete') -function getPosition(opt) { - let { line, linenr, colnr } = opt; - let part = string_1.byteSlice(line, 0, colnr - 1); - return { - line: linenr - 1, - character: part.length - }; -} -exports.getPosition = getPosition; -function getWord(item, opt, invalidInsertCharacters) { - // tslint:disable-next-line: deprecation - let { label, data, insertTextFormat, insertText, textEdit } = item; - let word; - let newText; - if (data && data.word) - return data.word; - if (textEdit) { - let { range } = textEdit; - newText = textEdit.newText; - if (range && range.start.line == range.end.line) { - let { line, col, colnr } = opt; - let character = string_1.characterIndex(line, col); - if (range.start.character > character) { - let before = line.slice(character - range.start.character); - newText = before + newText; - } - else { - let start = line.slice(range.start.character, character); - if (start.length && newText.startsWith(start)) { - newText = newText.slice(start.length); +const processes_1 = __webpack_require__(346); +const uuid = __webpack_require__(323); +const logger = __webpack_require__(2)('util-highlights'); +const diagnosticFiletypes = ['Error', 'Warning', 'Info', 'Hint']; +const cache = {}; +let env = null; +// get highlights by send text to another neovim instance. +function getHiglights(lines, filetype, timeout = 500) { + const hlMap = new Map(); + const content = lines.join('\n'); + if (diagnosticFiletypes.indexOf(filetype) != -1) { + let highlights = lines.map((line, i) => { + return { + line: i, + colStart: 0, + colEnd: string_1.byteLength(line), + hlGroup: `Coc${filetype}Float` + }; + }); + return Promise.resolve(highlights); + } + if (filetype == 'javascriptreact') { + filetype = 'javascript'; + } + if (filetype == 'typescriptreact') { + filetype = 'typescript'; + } + const id = crypto_1.createHash('md5').update(content).digest('hex'); + if (cache[id]) + return Promise.resolve(cache[id]); + if (workspace_1.default.env.isVim) + return Promise.resolve([]); + const res = []; + let nvim; + return new Promise(async (resolve) => { + if (!env) { + env = await workspace_1.default.nvim.call('coc#util#highlight_options'); + if (!env) + resolve([]); + let paths = env.runtimepath.split(','); + let dirs = paths.filter(p => { + if (env.colorscheme) { + let schemeFile = path_1.default.join(p, `colors/${env.colorscheme}.vim`); + if (fs_1.default.existsSync(schemeFile)) + return true; } + if (fs_1.default.existsSync(path_1.default.join(p, 'syntax'))) + return true; + if (fs_1.default.existsSync(path_1.default.join(p, 'after/syntax'))) + return true; + return false; + }); + env.runtimepath = dirs.join(','); + } + let prog = workspace_1.default.env.progpath || 'nvim'; + let proc = cp.spawn(prog, ['-u', 'NORC', '-i', 'NONE', '--embed', '--noplugin', uuid()], { + shell: false, + cwd: os_1.default.tmpdir(), + env: lodash_1.omit(process.env, ['NVIM_LISTEN_ADDRESS', 'VIM_NODE_RPC']) + }); + proc.on('error', error => { + logger.info('highlight error:', error); + resolve([]); + }); + let timer; + let exited = false; + const exit = () => { + if (exited) + return; + exited = true; + if (timer) + clearTimeout(timer); + if (nvim) { + nvim.command('qa!').catch(() => { + let killed = processes_1.terminate(proc); + if (!killed) { + setTimeout(() => { + processes_1.terminate(proc); + }, 50); + } + }); } - character = string_1.characterIndex(line, colnr - 1); - if (range.end.character > character) { - let end = line.slice(character, range.end.character); - if (newText.endsWith(end)) { - newText = newText.slice(0, -end.length); + }; + try { + proc.once('exit', () => { + if (exited) + return; + logger.info('highlight nvim exited.'); + resolve([]); + }); + timer = setTimeout(() => { + exit(); + resolve([]); + }, timeout); + nvim = neovim_1.attach({ proc }, null, false); + const callback = (method, args) => { + if (method == 'redraw') { + for (let arr of args) { + let [name, ...list] = arr; + if (name == 'hl_attr_define') { + for (let item of list) { + let id = item[0]; + let { hi_name } = item[item.length - 1][0]; + hlMap.set(id, hi_name); + } + } + if (name == 'grid_line') { + // logger.debug('list:', JSON.stringify(list, null, 2)) + for (let def of list) { + let [, line, col, cells] = def; + if (line >= lines.length) + continue; + let colStart = 0; + let hlGroup = ''; + let currId = 0; + // tslint:disable-next-line: prefer-for-of + for (let i = 0; i < cells.length; i++) { + let cell = cells[i]; + let [ch, hlId, repeat] = cell; + repeat = repeat || 1; + let len = string_1.byteLength(ch.repeat(repeat)); + // append result + if (hlId == 0 || (hlId > 0 && hlId != currId)) { + if (hlGroup) { + res.push({ + line, + hlGroup, + colStart, + colEnd: col, + isMarkdown: filetype == 'markdown' + }); + } + colStart = col; + hlGroup = hlId == 0 ? '' : hlMap.get(hlId); + } + if (hlId != null) + currId = hlId; + col = col + len; + } + if (hlGroup) { + res.push({ + hlGroup, + line, + colStart, + colEnd: col, + isMarkdown: filetype == 'markdown' + }); + } + } + cache[id] = res; + exit(); + resolve(res); + } + } } + }; + nvim.on('notification', callback); + await nvim.callAtomic([ + ['nvim_set_option', ['runtimepath', env.runtimepath]], + ['nvim_command', [`highlight! link Normal CocFloating`]], + ['nvim_command', [`runtime syntax/${filetype}.vim`]], + ['nvim_command', [`colorscheme ${env.colorscheme || 'default'}`]], + ['nvim_command', [`set background=${env.background}`]], + ['nvim_command', ['set nowrap']], + ['nvim_command', ['set noswapfile']], + ['nvim_command', ['set nobackup']], + ['nvim_command', ['set noshowmode']], + ['nvim_command', ['set noruler']], + ['nvim_command', ['set laststatus=0']], + ]); + let buf = await nvim.buffer; + await buf.setLines(lines, { start: 0, end: -1, strictIndexing: false }); + await buf.setOption('filetype', filetype); + await nvim.uiAttach(200, lines.length + 1, { + ext_hlstate: true, + ext_linegrid: true + }); + } + catch (e) { + logger.error(e); + exit(); + resolve([]); + } + }); +} +exports.getHiglights = getHiglights; +//# sourceMappingURL=highlight.js.map + +/***/ }), +/* 346 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const tslib_1 = __webpack_require__(3); +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +const cp = tslib_1.__importStar(__webpack_require__(178)); +const path_1 = __webpack_require__(20); +const isWebpack = typeof __webpack_require__ === "function"; +const isWindows = process.platform === 'win32'; +const isMacintosh = process.platform === 'darwin'; +const isLinux = process.platform === 'linux'; +const pluginRoot = isWebpack ? path_1.dirname(__dirname) : path_1.resolve(__dirname, '../..'); +function terminate(process, cwd) { + if (isWindows) { + try { + // This we run in Atom execFileSync is available. + // Ignore stderr since this is otherwise piped to parent.stderr + // which might be already closed. + let options = { + stdio: ['pipe', 'pipe', 'ignore'] + }; + if (cwd) { + options.cwd = cwd; } + cp.execFileSync('taskkill', ['/T', '/F', '/PID', process.pid.toString()], options); + return true; + } + catch (err) { + return false; } } - else { - newText = insertText; - } - if (insertTextFormat == vscode_languageserver_types_1.InsertTextFormat.Snippet - && newText - && newText.indexOf('$') !== -1) { - let parser = new parser_1.SnippetParser(); - let snippet = parser.text(newText); - word = snippet ? getValidWord(snippet, invalidInsertCharacters) : label; + else if (isLinux || isMacintosh) { + try { + let cmd = path_1.join(pluginRoot, 'bin/terminateProcess.sh'); + let result = cp.spawnSync(cmd, [process.pid.toString()]); + return result.error ? false : true; + } + catch (err) { + return false; + } } else { - word = getValidWord(newText, invalidInsertCharacters) || label; - } - return word; -} -exports.getWord = getWord; -function getDocumentation(item) { - let { documentation } = item; - if (!documentation) - return ''; - if (typeof documentation === 'string') - return documentation; - return documentation.value; -} -exports.getDocumentation = getDocumentation; -function completionKindString(kind, map, defaultValue = '') { - return map.get(kind) || defaultValue; -} -exports.completionKindString = completionKindString; -function getSnippetDocumentation(languageId, body) { - languageId = languageId.replace(/react$/, ''); - let str = body.replace(/\$\d+/g, '').replace(/\$\{\d+(?::([^{]+))?\}/, '$1'); - str = '``` ' + languageId + '\n' + str + '\n' + '```'; - return str; -} -exports.getSnippetDocumentation = getSnippetDocumentation; -function getValidWord(text, invalidChars) { - if (!text) - return ''; - for (let i = 0; i < text.length; i++) { - let c = text[i]; - if (invalidChars.indexOf(c) !== -1) { - return text.slice(0, i); - } + process.kill('SIGKILL'); + return true; } - return text; } -exports.getValidWord = getValidWord; -//# sourceMappingURL=complete.js.map +exports.terminate = terminate; +//# sourceMappingURL=processes.js.map /***/ }), -/* 352 */ +/* 347 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const ansiparse_1 = __webpack_require__(353); +const ansiparse_1 = __webpack_require__(348); const string_1 = __webpack_require__(213); /** * Build highlights, with lines and highlights @@ -53742,7 +53164,7 @@ exports.default = Highlighter; //# sourceMappingURL=highligher.js.map /***/ }), -/* 353 */ +/* 348 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53961,7 +53383,7 @@ exports.ansiparse = ansiparse; //# sourceMappingURL=ansiparse.js.map /***/ }), -/* 354 */ +/* 349 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53973,7 +53395,7 @@ const fs_1 = tslib_1.__importDefault(__webpack_require__(4)); const net_1 = tslib_1.__importDefault(__webpack_require__(96)); const os_1 = tslib_1.__importDefault(__webpack_require__(14)); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const language_client_1 = __webpack_require__(355); +const language_client_1 = __webpack_require__(350); const types_1 = __webpack_require__(192); const util_1 = __webpack_require__(177); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); @@ -54421,7 +53843,7 @@ exports.default = new ServiceManager(); //# sourceMappingURL=services.js.map /***/ }), -/* 355 */ +/* 350 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54441,21 +53863,21 @@ const which_1 = tslib_1.__importDefault(__webpack_require__(184)); const types_1 = __webpack_require__(192); const util_1 = __webpack_require__(177); const Is = tslib_1.__importStar(__webpack_require__(194)); -const processes_1 = __webpack_require__(323); +const processes_1 = __webpack_require__(346); const string_1 = __webpack_require__(213); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const client_1 = __webpack_require__(356); -const colorProvider_1 = __webpack_require__(361); -const configuration_1 = __webpack_require__(362); -const declaration_1 = __webpack_require__(363); -const foldingRange_1 = __webpack_require__(364); -const implementation_1 = __webpack_require__(365); -const progress_1 = __webpack_require__(366); -const typeDefinition_1 = __webpack_require__(367); -const workspaceFolders_1 = __webpack_require__(368); -const selectionRange_1 = __webpack_require__(369); +const client_1 = __webpack_require__(351); +const colorProvider_1 = __webpack_require__(356); +const configuration_1 = __webpack_require__(357); +const declaration_1 = __webpack_require__(358); +const foldingRange_1 = __webpack_require__(359); +const implementation_1 = __webpack_require__(360); +const progress_1 = __webpack_require__(361); +const typeDefinition_1 = __webpack_require__(362); +const workspaceFolders_1 = __webpack_require__(363); +const selectionRange_1 = __webpack_require__(364); const logger = __webpack_require__(2)('language-client-index'); -tslib_1.__exportStar(__webpack_require__(356), exports); +tslib_1.__exportStar(__webpack_require__(351), exports); var Executable; (function (Executable) { function is(value) { @@ -54906,7 +54328,7 @@ var ProposedFeatures; //# sourceMappingURL=index.js.map /***/ }), -/* 356 */ +/* 351 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54922,16 +54344,16 @@ const path_1 = tslib_1.__importDefault(__webpack_require__(20)); const vscode_languageserver_protocol_1 = __webpack_require__(150); const vscode_uri_1 = __webpack_require__(183); const commands_1 = tslib_1.__importDefault(__webpack_require__(247)); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); const util_1 = __webpack_require__(177); const fs_1 = __webpack_require__(203); const Is = tslib_1.__importStar(__webpack_require__(194)); -const lodash_1 = __webpack_require__(315); +const lodash_1 = __webpack_require__(317); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const progressPart_1 = __webpack_require__(357); -const async_1 = __webpack_require__(358); -const cv = tslib_1.__importStar(__webpack_require__(359)); -const UUID = tslib_1.__importStar(__webpack_require__(360)); +const progressPart_1 = __webpack_require__(352); +const async_1 = __webpack_require__(353); +const cv = tslib_1.__importStar(__webpack_require__(354)); +const UUID = tslib_1.__importStar(__webpack_require__(355)); const logger = __webpack_require__(2)('language-client-client'); class ConsoleLogger { error(message) { @@ -57217,7 +56639,7 @@ class BaseLanguageClient { } } notifyFileEvent(event) { - var _a, _b; + var _a; const client = this; function didChangeWatchedFile(event) { client._fileEvents.push(event); @@ -57236,7 +56658,7 @@ class BaseLanguageClient { }); } const workSpaceMiddleware = (_a = this.clientOptions.middleware) === null || _a === void 0 ? void 0 : _a.workspace; - ((_b = workSpaceMiddleware) === null || _b === void 0 ? void 0 : _b.didChangeWatchedFile) ? workSpaceMiddleware.didChangeWatchedFile(event, didChangeWatchedFile) : didChangeWatchedFile(event); + (workSpaceMiddleware === null || workSpaceMiddleware === void 0 ? void 0 : workSpaceMiddleware.didChangeWatchedFile) ? workSpaceMiddleware.didChangeWatchedFile(event, didChangeWatchedFile) : didChangeWatchedFile(event); } forceDocumentSync() { let doc = workspace_1.default.getDocument(workspace_1.default.bufnr); @@ -57516,7 +56938,7 @@ exports.BaseLanguageClient = BaseLanguageClient; //# sourceMappingURL=client.js.map /***/ }), -/* 357 */ +/* 352 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57586,7 +57008,7 @@ exports.ProgressPart = ProgressPart; //# sourceMappingURL=progressPart.js.map /***/ }), -/* 358 */ +/* 353 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57668,13 +57090,13 @@ exports.Delayer = Delayer; //# sourceMappingURL=async.js.map /***/ }), -/* 359 */ +/* 354 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const lodash_1 = __webpack_require__(315); +const lodash_1 = __webpack_require__(317); function asLanguageIds(documentSelector) { let res = documentSelector.map(filter => { if (typeof filter == 'string') { @@ -57796,13 +57218,13 @@ exports.asCodeLensParams = asCodeLensParams; //# sourceMappingURL=converter.js.map /***/ }), -/* 360 */ +/* 355 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const uuidv4 = __webpack_require__(324); +const uuidv4 = __webpack_require__(323); function generateUuid() { return uuidv4(); } @@ -57810,7 +57232,7 @@ exports.generateUuid = generateUuid; //# sourceMappingURL=uuid.js.map /***/ }), -/* 361 */ +/* 356 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57822,8 +57244,8 @@ exports.generateUuid = generateUuid; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); -const client_1 = __webpack_require__(356); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); +const client_1 = __webpack_require__(351); function ensure(target, key) { if (target[key] === void 0) { target[key] = {}; @@ -57888,7 +57310,7 @@ exports.ColorProviderFeature = ColorProviderFeature; //# sourceMappingURL=colorProvider.js.map /***/ }), -/* 362 */ +/* 357 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57962,7 +57384,7 @@ exports.ConfigurationFeature = ConfigurationFeature; //# sourceMappingURL=configuration.js.map /***/ }), -/* 363 */ +/* 358 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57974,9 +57396,9 @@ exports.ConfigurationFeature = ConfigurationFeature; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); -const client_1 = __webpack_require__(356); -const converter_1 = __webpack_require__(359); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); +const client_1 = __webpack_require__(351); +const converter_1 = __webpack_require__(354); function ensure(target, key) { if (target[key] === void 0) { target[key] = {}; @@ -58022,7 +57444,7 @@ exports.DeclarationFeature = DeclarationFeature; //# sourceMappingURL=declaration.js.map /***/ }), -/* 364 */ +/* 359 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58034,8 +57456,8 @@ exports.DeclarationFeature = DeclarationFeature; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); -const client_1 = __webpack_require__(356); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); +const client_1 = __webpack_require__(351); function ensure(target, key) { if (target[key] === void 0) { target[key] = {}; @@ -58085,7 +57507,7 @@ exports.FoldingRangeFeature = FoldingRangeFeature; //# sourceMappingURL=foldingRange.js.map /***/ }), -/* 365 */ +/* 360 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58097,9 +57519,9 @@ const tslib_1 = __webpack_require__(3); * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ const vscode_languageserver_protocol_1 = __webpack_require__(150); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); -const client_1 = __webpack_require__(356); -const cv = tslib_1.__importStar(__webpack_require__(359)); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); +const client_1 = __webpack_require__(351); +const cv = tslib_1.__importStar(__webpack_require__(354)); function ensure(target, key) { if (target[key] === void 0) { target[key] = {}; @@ -58145,7 +57567,7 @@ exports.ImplementationFeature = ImplementationFeature; //# sourceMappingURL=implementation.js.map /***/ }), -/* 366 */ +/* 361 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58156,7 +57578,7 @@ exports.ImplementationFeature = ImplementationFeature; Object.defineProperty(exports, "__esModule", { value: true }); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const progressPart_1 = __webpack_require__(357); +const progressPart_1 = __webpack_require__(352); function ensure(target, key) { if (target[key] === void 0) { target[key] = Object.create(null); @@ -58182,7 +57604,7 @@ exports.ProgressFeature = ProgressFeature; //# sourceMappingURL=progress.js.map /***/ }), -/* 367 */ +/* 362 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58194,9 +57616,9 @@ const tslib_1 = __webpack_require__(3); * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ const vscode_languageserver_protocol_1 = __webpack_require__(150); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); -const client_1 = __webpack_require__(356); -const cv = tslib_1.__importStar(__webpack_require__(359)); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); +const client_1 = __webpack_require__(351); +const cv = tslib_1.__importStar(__webpack_require__(354)); function ensure(target, key) { if (target[key] === void 0) { target[key] = {}; @@ -58242,7 +57664,7 @@ exports.TypeDefinitionFeature = TypeDefinitionFeature; //# sourceMappingURL=typeDefinition.js.map /***/ }), -/* 368 */ +/* 363 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58255,7 +57677,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const UUID = tslib_1.__importStar(__webpack_require__(360)); +const UUID = tslib_1.__importStar(__webpack_require__(355)); const logger = __webpack_require__(2)('language-client-workspaceFolder'); function access(target, key) { if (target === void 0) { @@ -58386,7 +57808,7 @@ exports.WorkspaceFoldersFeature = WorkspaceFoldersFeature; //# sourceMappingURL=workspaceFolders.js.map /***/ }), -/* 369 */ +/* 364 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58398,8 +57820,8 @@ exports.WorkspaceFoldersFeature = WorkspaceFoldersFeature; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); -const client_1 = __webpack_require__(356); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); +const client_1 = __webpack_require__(351); function ensure(target, key) { if (target[key] === void 0) { target[key] = {}; @@ -58448,7 +57870,7 @@ exports.SelectionRangeFeature = SelectionRangeFeature; //# sourceMappingURL=selectionRange.js.map /***/ }), -/* 370 */ +/* 365 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58458,29 +57880,29 @@ const tslib_1 = __webpack_require__(3); const debounce_1 = tslib_1.__importDefault(__webpack_require__(179)); const vscode_languageserver_protocol_1 = __webpack_require__(150); const events_1 = tslib_1.__importDefault(__webpack_require__(149)); -const extensions_1 = tslib_1.__importDefault(__webpack_require__(253)); +const extensions_1 = tslib_1.__importDefault(__webpack_require__(255)); const util_1 = __webpack_require__(177); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const highligher_1 = tslib_1.__importDefault(__webpack_require__(352)); -const configuration_1 = tslib_1.__importDefault(__webpack_require__(371)); -const history_1 = tslib_1.__importDefault(__webpack_require__(372)); -const mappings_1 = tslib_1.__importDefault(__webpack_require__(374)); -const prompt_1 = tslib_1.__importDefault(__webpack_require__(375)); -const commands_1 = tslib_1.__importDefault(__webpack_require__(376)); -const diagnostics_1 = tslib_1.__importDefault(__webpack_require__(378)); -const extensions_2 = tslib_1.__importDefault(__webpack_require__(380)); -const folders_1 = tslib_1.__importDefault(__webpack_require__(381)); -const links_1 = tslib_1.__importDefault(__webpack_require__(382)); -const lists_1 = tslib_1.__importDefault(__webpack_require__(383)); -const location_1 = tslib_1.__importDefault(__webpack_require__(379)); -const outline_1 = tslib_1.__importDefault(__webpack_require__(384)); -const output_1 = tslib_1.__importDefault(__webpack_require__(386)); -const services_1 = tslib_1.__importDefault(__webpack_require__(387)); -const sources_1 = tslib_1.__importDefault(__webpack_require__(388)); -const symbols_1 = tslib_1.__importDefault(__webpack_require__(389)); -const actions_1 = tslib_1.__importDefault(__webpack_require__(391)); -const ui_1 = tslib_1.__importDefault(__webpack_require__(392)); -const worker_1 = tslib_1.__importDefault(__webpack_require__(393)); +const highligher_1 = tslib_1.__importDefault(__webpack_require__(347)); +const configuration_1 = tslib_1.__importDefault(__webpack_require__(366)); +const history_1 = tslib_1.__importDefault(__webpack_require__(367)); +const mappings_1 = tslib_1.__importDefault(__webpack_require__(369)); +const prompt_1 = tslib_1.__importDefault(__webpack_require__(370)); +const commands_1 = tslib_1.__importDefault(__webpack_require__(371)); +const diagnostics_1 = tslib_1.__importDefault(__webpack_require__(373)); +const extensions_2 = tslib_1.__importDefault(__webpack_require__(375)); +const folders_1 = tslib_1.__importDefault(__webpack_require__(376)); +const links_1 = tslib_1.__importDefault(__webpack_require__(377)); +const lists_1 = tslib_1.__importDefault(__webpack_require__(378)); +const location_1 = tslib_1.__importDefault(__webpack_require__(374)); +const outline_1 = tslib_1.__importDefault(__webpack_require__(379)); +const output_1 = tslib_1.__importDefault(__webpack_require__(381)); +const services_1 = tslib_1.__importDefault(__webpack_require__(382)); +const sources_1 = tslib_1.__importDefault(__webpack_require__(383)); +const symbols_1 = tslib_1.__importDefault(__webpack_require__(384)); +const actions_1 = tslib_1.__importDefault(__webpack_require__(386)); +const ui_1 = tslib_1.__importDefault(__webpack_require__(387)); +const worker_1 = tslib_1.__importDefault(__webpack_require__(388)); const semver_1 = tslib_1.__importDefault(__webpack_require__(1)); const logger = __webpack_require__(2)('list-manager'); const mouseKeys = ['', '', '', '<2-LeftMouse>']; @@ -59239,7 +58661,7 @@ exports.default = new ListManager(); //# sourceMappingURL=manager.js.map /***/ }), -/* 371 */ +/* 366 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59355,14 +58777,14 @@ exports.default = ListConfiguration; //# sourceMappingURL=configuration.js.map /***/ }), -/* 372 */ +/* 367 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); -const fuzzy_1 = __webpack_require__(373); +const fuzzy_1 = __webpack_require__(368); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); const logger = __webpack_require__(2)('list-history'); class History { @@ -59442,7 +58864,7 @@ exports.default = History; //# sourceMappingURL=history.js.map /***/ }), -/* 373 */ +/* 368 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59505,16 +58927,16 @@ exports.fuzzyMatch = fuzzyMatch; //# sourceMappingURL=fuzzy.js.map /***/ }), -/* 374 */ +/* 369 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); -__webpack_require__(312); +__webpack_require__(314); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const configuration_1 = __webpack_require__(371); +const configuration_1 = __webpack_require__(366); const logger = __webpack_require__(2)('list-mappings'); class Mappings { constructor(manager, nvim, config) { @@ -59871,7 +59293,7 @@ exports.default = Mappings; //# sourceMappingURL=mappings.js.map /***/ }), -/* 375 */ +/* 370 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60086,7 +59508,7 @@ exports.default = Prompt; //# sourceMappingURL=prompt.js.map /***/ }), -/* 376 */ +/* 371 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60096,7 +59518,7 @@ const tslib_1 = __webpack_require__(3); const commands_1 = tslib_1.__importDefault(__webpack_require__(247)); const events_1 = tslib_1.__importDefault(__webpack_require__(149)); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const basic_1 = tslib_1.__importDefault(__webpack_require__(377)); +const basic_1 = tslib_1.__importDefault(__webpack_require__(372)); class CommandsList extends basic_1.default { constructor(nvim) { super(nvim); @@ -60160,7 +59582,7 @@ function score(list, key) { //# sourceMappingURL=commands.js.map /***/ }), -/* 377 */ +/* 372 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60175,7 +59597,7 @@ const util_1 = __webpack_require__(177); const position_1 = __webpack_require__(216); const string_1 = __webpack_require__(213); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const configuration_1 = tslib_1.__importDefault(__webpack_require__(371)); +const configuration_1 = tslib_1.__importDefault(__webpack_require__(366)); const logger = __webpack_require__(2)('list-basic'); class BasicList { constructor(nvim) { @@ -60490,7 +59912,7 @@ exports.default = BasicList; //# sourceMappingURL=basic.js.map /***/ }), -/* 378 */ +/* 373 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60498,8 +59920,8 @@ exports.default = BasicList; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const path_1 = tslib_1.__importDefault(__webpack_require__(20)); -const manager_1 = tslib_1.__importDefault(__webpack_require__(319)); -const location_1 = tslib_1.__importDefault(__webpack_require__(379)); +const manager_1 = tslib_1.__importDefault(__webpack_require__(248)); +const location_1 = tslib_1.__importDefault(__webpack_require__(374)); const fs_1 = __webpack_require__(203); const logger = __webpack_require__(2)('list-symbols'); class DiagnosticsList extends location_1.default { @@ -60542,7 +59964,7 @@ exports.default = DiagnosticsList; //# sourceMappingURL=diagnostics.js.map /***/ }), -/* 379 */ +/* 374 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60551,7 +59973,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_types_1 = __webpack_require__(162); const path_1 = tslib_1.__importDefault(__webpack_require__(20)); -const basic_1 = tslib_1.__importDefault(__webpack_require__(377)); +const basic_1 = tslib_1.__importDefault(__webpack_require__(372)); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); const vscode_uri_1 = __webpack_require__(183); const fs_1 = __webpack_require__(203); @@ -60621,7 +60043,7 @@ exports.default = LocationList; //# sourceMappingURL=location.js.map /***/ }), -/* 380 */ +/* 375 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60630,10 +60052,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const os_1 = tslib_1.__importDefault(__webpack_require__(14)); const path_1 = tslib_1.__importDefault(__webpack_require__(20)); -const extensions_1 = tslib_1.__importDefault(__webpack_require__(253)); +const extensions_1 = tslib_1.__importDefault(__webpack_require__(255)); const util_1 = __webpack_require__(177); const fs_1 = __webpack_require__(203); -const basic_1 = tslib_1.__importDefault(__webpack_require__(377)); +const basic_1 = tslib_1.__importDefault(__webpack_require__(372)); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); const logger = __webpack_require__(2)('list-extensions'); class ExtensionList extends basic_1.default { @@ -60772,7 +60194,7 @@ function getPriority(stat) { //# sourceMappingURL=extensions.js.map /***/ }), -/* 381 */ +/* 376 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60781,7 +60203,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const fs_1 = __webpack_require__(203); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const basic_1 = tslib_1.__importDefault(__webpack_require__(377)); +const basic_1 = tslib_1.__importDefault(__webpack_require__(372)); const vscode_uri_1 = __webpack_require__(183); const util_1 = __webpack_require__(177); const path_1 = tslib_1.__importDefault(__webpack_require__(20)); @@ -60828,17 +60250,17 @@ exports.default = FoldList; //# sourceMappingURL=folders.js.map /***/ }), -/* 382 */ +/* 377 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); const path_1 = tslib_1.__importDefault(__webpack_require__(20)); -const basic_1 = tslib_1.__importDefault(__webpack_require__(377)); +const basic_1 = tslib_1.__importDefault(__webpack_require__(372)); const vscode_languageserver_types_1 = __webpack_require__(162); const vscode_uri_1 = __webpack_require__(183); const fs_1 = __webpack_require__(203); @@ -60911,14 +60333,14 @@ function formatUri(uri) { //# sourceMappingURL=links.js.map /***/ }), -/* 383 */ +/* 378 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); -const basic_1 = tslib_1.__importDefault(__webpack_require__(377)); +const basic_1 = tslib_1.__importDefault(__webpack_require__(372)); const mru_1 = tslib_1.__importDefault(__webpack_require__(218)); class LinksList extends basic_1.default { constructor(nvim, listMap) { @@ -60972,7 +60394,7 @@ function score(list, key) { //# sourceMappingURL=lists.js.map /***/ }), -/* 384 */ +/* 379 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60983,12 +60405,12 @@ const path_1 = tslib_1.__importDefault(__webpack_require__(20)); const vscode_languageserver_types_1 = __webpack_require__(162); const vscode_uri_1 = __webpack_require__(183); const which_1 = tslib_1.__importDefault(__webpack_require__(184)); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); const util_1 = __webpack_require__(177); const fs_1 = __webpack_require__(203); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const location_1 = tslib_1.__importDefault(__webpack_require__(379)); -const convert_1 = __webpack_require__(385); +const location_1 = tslib_1.__importDefault(__webpack_require__(374)); +const convert_1 = __webpack_require__(380); const logger = __webpack_require__(2)('list-symbols'); function getFilterText(s, args) { let result = s.name; @@ -61141,7 +60563,7 @@ function sortSymbols(a, b) { //# sourceMappingURL=outline.js.map /***/ }), -/* 385 */ +/* 380 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61210,7 +60632,7 @@ exports.getSymbolKind = getSymbolKind; //# sourceMappingURL=convert.js.map /***/ }), -/* 386 */ +/* 381 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61218,7 +60640,7 @@ exports.getSymbolKind = getSymbolKind; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const basic_1 = tslib_1.__importDefault(__webpack_require__(377)); +const basic_1 = tslib_1.__importDefault(__webpack_require__(372)); class OutputList extends basic_1.default { constructor(nvim) { super(nvim); @@ -61240,15 +60662,15 @@ exports.default = OutputList; //# sourceMappingURL=output.js.map /***/ }), -/* 387 */ +/* 382 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); -const services_1 = tslib_1.__importDefault(__webpack_require__(354)); -const basic_1 = tslib_1.__importDefault(__webpack_require__(377)); +const services_1 = tslib_1.__importDefault(__webpack_require__(349)); +const basic_1 = tslib_1.__importDefault(__webpack_require__(372)); const util_1 = __webpack_require__(177); class ServicesList extends basic_1.default { constructor(nvim) { @@ -61295,7 +60717,7 @@ exports.default = ServicesList; //# sourceMappingURL=services.js.map /***/ }), -/* 388 */ +/* 383 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61304,8 +60726,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_types_1 = __webpack_require__(162); const vscode_uri_1 = __webpack_require__(183); -const sources_1 = tslib_1.__importDefault(__webpack_require__(252)); -const basic_1 = tslib_1.__importDefault(__webpack_require__(377)); +const sources_1 = tslib_1.__importDefault(__webpack_require__(254)); +const basic_1 = tslib_1.__importDefault(__webpack_require__(372)); class SourcesList extends basic_1.default { constructor(nvim) { super(nvim); @@ -61366,7 +60788,7 @@ exports.default = SourcesList; //# sourceMappingURL=sources.js.map /***/ }), -/* 389 */ +/* 384 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61375,12 +60797,12 @@ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const path_1 = tslib_1.__importDefault(__webpack_require__(20)); const vscode_uri_1 = __webpack_require__(183); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const location_1 = tslib_1.__importDefault(__webpack_require__(379)); -const convert_1 = __webpack_require__(385); +const location_1 = tslib_1.__importDefault(__webpack_require__(374)); +const convert_1 = __webpack_require__(380); const fs_1 = __webpack_require__(203); -const fzy_1 = __webpack_require__(390); +const fzy_1 = __webpack_require__(385); const logger = __webpack_require__(2)('list-symbols'); class Symbols extends location_1.default { constructor() { @@ -61474,7 +60896,7 @@ exports.default = Symbols; //# sourceMappingURL=symbols.js.map /***/ }), -/* 390 */ +/* 385 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61645,7 +61067,7 @@ exports.hasMatch = hasMatch; //# sourceMappingURL=fzy.js.map /***/ }), -/* 391 */ +/* 386 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61654,11 +61076,11 @@ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); const commands_1 = tslib_1.__importDefault(__webpack_require__(247)); -const manager_1 = tslib_1.__importDefault(__webpack_require__(319)); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); -const services_1 = tslib_1.__importDefault(__webpack_require__(354)); +const manager_1 = tslib_1.__importDefault(__webpack_require__(248)); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); +const services_1 = tslib_1.__importDefault(__webpack_require__(349)); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const basic_1 = tslib_1.__importDefault(__webpack_require__(377)); +const basic_1 = tslib_1.__importDefault(__webpack_require__(372)); const logger = __webpack_require__(2)('list-actions'); class ActionsList extends basic_1.default { constructor(nvim) { @@ -61775,7 +61197,7 @@ exports.default = ActionsList; //# sourceMappingURL=actions.js.map /***/ }), -/* 392 */ +/* 387 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62252,7 +61674,7 @@ exports.default = ListUI; //# sourceMappingURL=ui.js.map /***/ }), -/* 393 */ +/* 388 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62261,10 +61683,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); const vscode_uri_1 = __webpack_require__(183); -const ansiparse_1 = __webpack_require__(353); +const ansiparse_1 = __webpack_require__(348); const diff_1 = __webpack_require__(211); -const fzy_1 = __webpack_require__(390); -const score_1 = __webpack_require__(394); +const fzy_1 = __webpack_require__(385); +const score_1 = __webpack_require__(389); const string_1 = __webpack_require__(213); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; @@ -62686,14 +62108,14 @@ function getItemUri(item) { //# sourceMappingURL=worker.js.map /***/ }), -/* 394 */ +/* 389 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = __webpack_require__(20); -const fuzzy_1 = __webpack_require__(373); +const fuzzy_1 = __webpack_require__(368); // first is start or path start +1, fuzzy +0.5 // next is followed of path start +1, fuzzy +0.5 // filename startsWith +1, fuzzy +0.5 @@ -62837,7 +62259,7 @@ function bestResult(results) { //# sourceMappingURL=score.js.map /***/ }), -/* 395 */ +/* 390 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63006,17 +62428,17 @@ exports.default = Source; //# sourceMappingURL=source.js.map /***/ }), -/* 396 */ +/* 391 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); -const fuzzy_1 = __webpack_require__(373); +const fuzzy_1 = __webpack_require__(368); const string_1 = __webpack_require__(213); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const source_1 = tslib_1.__importDefault(__webpack_require__(395)); +const source_1 = tslib_1.__importDefault(__webpack_require__(390)); const logger = __webpack_require__(2)('model-source-vim'); class VimSource extends source_1.default { async callOptinalFunc(fname, args) { @@ -63118,7 +62540,7 @@ exports.default = VimSource; //# sourceMappingURL=source-vim.js.map /***/ }), -/* 397 */ +/* 392 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63126,7 +62548,7 @@ exports.default = VimSource; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const source_1 = tslib_1.__importDefault(__webpack_require__(395)); +const source_1 = tslib_1.__importDefault(__webpack_require__(390)); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); const logger = __webpack_require__(2)('source-around'); class Around extends source_1.default { @@ -63168,7 +62590,7 @@ exports.regist = regist; //# sourceMappingURL=around.js.map /***/ }), -/* 398 */ +/* 393 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63176,7 +62598,7 @@ exports.regist = regist; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const source_1 = tslib_1.__importDefault(__webpack_require__(395)); +const source_1 = tslib_1.__importDefault(__webpack_require__(390)); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); const logger = __webpack_require__(2)('source-buffer'); class Buffer extends source_1.default { @@ -63232,7 +62654,7 @@ exports.regist = regist; //# sourceMappingURL=buffer.js.map /***/ }), -/* 399 */ +/* 394 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63245,7 +62667,7 @@ const os_1 = tslib_1.__importDefault(__webpack_require__(14)); const path_1 = tslib_1.__importDefault(__webpack_require__(20)); const util_1 = tslib_1.__importDefault(__webpack_require__(12)); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const source_1 = tslib_1.__importDefault(__webpack_require__(395)); +const source_1 = tslib_1.__importDefault(__webpack_require__(390)); const fs_2 = __webpack_require__(203); const string_1 = __webpack_require__(213); const logger = __webpack_require__(2)('source-file'); @@ -63390,16 +62812,16 @@ exports.regist = regist; //# sourceMappingURL=file.js.map /***/ }), -/* 400 */ +/* 395 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const vscode_languageserver_protocol_1 = __webpack_require__(150); -const fuzzy_1 = __webpack_require__(373); +const fuzzy_1 = __webpack_require__(368); const string_1 = __webpack_require__(213); -const match_1 = __webpack_require__(401); +const match_1 = __webpack_require__(396); const logger = __webpack_require__(2)('completion-complete'); // first time completion const FIRST_TIMEOUT = 500; @@ -63772,13 +63194,13 @@ exports.default = Complete; //# sourceMappingURL=complete.js.map /***/ }), -/* 401 */ +/* 396 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fuzzy_1 = __webpack_require__(373); +const fuzzy_1 = __webpack_require__(368); function nextWordIndex(start = 0, codes) { for (let i = start; i < codes.length; i++) { if (isWordIndex(i, codes)) { @@ -63928,15 +63350,15 @@ function nextScore(codes, index, inputCodes, allowFuzzy = true) { //# sourceMappingURL=match.js.map /***/ }), -/* 402 */ +/* 397 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); -const floatBuffer_1 = tslib_1.__importDefault(__webpack_require__(321)); -const popup_1 = tslib_1.__importDefault(__webpack_require__(325)); +const floatBuffer_1 = tslib_1.__importDefault(__webpack_require__(344)); +const popup_1 = tslib_1.__importDefault(__webpack_require__(398)); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); const logger = __webpack_require__(2)('floating'); class Floating { @@ -64126,7 +63548,74 @@ exports.default = Floating; //# sourceMappingURL=floating.js.map /***/ }), -/* 403 */ +/* 398 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +class Popup { + constructor(nvim) { + this.nvim = nvim; + } + async create(text, options) { + let { nvim } = this; + this.id = await nvim.call('popup_create', [text, options]); + this.bufferId = await nvim.call('winbufnr', [this.id]); + } + hide() { + if (!this.id) + return; + this.nvim.call('popup_hide', [this.id], true); + } + async valid() { + if (!this.bufferId) + return false; + await this.nvim.call('bufexists', [this.bufferId]); + } + async visible() { + if (!this.id) + return false; + let opt = await this.nvim.call('popup_getpos', [this.id]); + return opt && opt.visible == 1; + } + show() { + if (!this.id) + return; + this.nvim.call('popup_show', [this.id], true); + } + move(options) { + if (!this.id) + return; + this.nvim.call('popup_move', [this.id, options], true); + } + async getPosition() { + return await this.nvim.call('popup_getpos', [this.id]); + } + setFiletype(filetype) { + if (!this.id) + return; + let { nvim } = this; + // nvim.call('win_execute', [this.id, 'syntax enable'], true) + nvim.call('setbufvar', [this.bufferId, '&filetype', filetype], true); + } + dispose() { + if (this.id) { + this.nvim.call('popup_close', [this.id], true); + } + } +} +exports.Popup = Popup; +async function createPopup(nvim, text, options) { + let popup = new Popup(nvim); + await popup.create(text, options); + return popup; +} +exports.default = createPopup; +//# sourceMappingURL=popup.js.map + +/***/ }), +/* 399 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64135,7 +63624,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); const position_1 = __webpack_require__(216); -const Snippets = tslib_1.__importStar(__webpack_require__(249)); +const Snippets = tslib_1.__importStar(__webpack_require__(251)); const string_1 = __webpack_require__(213); const logger = __webpack_require__(2)('snippets-snipet'); class CocSnippet { @@ -64310,7 +63799,7 @@ exports.CocSnippet = CocSnippet; //# sourceMappingURL=snippet.js.map /***/ }), -/* 404 */ +/* 400 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64376,6 +63865,517 @@ class SnippetVariableResolver { exports.SnippetVariableResolver = SnippetVariableResolver; //# sourceMappingURL=variableResolve.js.map +/***/ }), +/* 401 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const tslib_1 = __webpack_require__(3); +const vscode_languageserver_protocol_1 = __webpack_require__(150); +const callSequence_1 = tslib_1.__importDefault(__webpack_require__(402)); +const object_1 = __webpack_require__(193); +const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); +const util_1 = __webpack_require__(403); +const logger = __webpack_require__(2)('diagnostic-buffer'); +const severityNames = ['CocError', 'CocWarning', 'CocInfo', 'CocHint']; +// maintains sign and highlightId +class DiagnosticBuffer { + constructor(bufnr, config) { + this.config = config; + this.signIds = new Set(); + this.sequence = null; + this._onDidRefresh = new vscode_languageserver_protocol_1.Emitter(); + this.matchIds = new Set(); + this.diagnostics = []; + this.onDidRefresh = this._onDidRefresh.event; + this.bufnr = bufnr; + this.srdId = workspace_1.default.createNameSpace('coc-diagnostic'); + let timer = null; + let time = Date.now(); + this.refresh = (diagnostics) => { + time = Date.now(); + if (timer) + clearTimeout(timer); + timer = setTimeout(async () => { + let current = time; + if (this.sequence) { + await this.sequence.cancel(); + } + // staled + if (current != time || !this.document) + return; + diagnostics.forEach(o => { + o.range = this.fixRange(o.range); + }); + this._refresh(diagnostics); + }, 30); + }; + } + _refresh(diagnostics) { + if (object_1.equals(this.diagnostics, diagnostics)) + return; + let { nvim } = this; + let sequence = this.sequence = new callSequence_1.default(); + let winid; + let bufnr; + sequence.addFunction(async () => { + let arr = await nvim.eval(`[coc#util#valid_state(), bufwinid(${this.bufnr}), bufnr("%")]`); + if (arr[0] == 0 || !this.document) + return true; + winid = arr[1]; + bufnr = arr[2]; + }); + sequence.addFunction(async () => { + nvim.pauseNotification(); + this.setDiagnosticInfo(bufnr, diagnostics); + this.addSigns(diagnostics); + this.setLocationlist(diagnostics, winid); + this.addHighlight(diagnostics, winid); + this.addDiagnosticVText(diagnostics); + let [, err] = await this.nvim.resumeNotification(); + if (err) + logger.error('Diagnostic error:', err); + }); + sequence.start().then(async (canceled) => { + if (!canceled) { + this.diagnostics = diagnostics; + this._onDidRefresh.fire(void 0); + } + }, e => { + logger.error(e); + }); + } + setLocationlist(diagnostics, winid) { + if (!this.config.locationlist) + return; + let { nvim, bufnr } = this; + // not shown + if (winid == -1) + return; + let items = []; + for (let diagnostic of diagnostics) { + let item = util_1.getLocationListItem(diagnostic.source, bufnr, diagnostic); + items.push(item); + } + nvim.call('setloclist', [winid, [], ' ', { title: 'Diagnostics of coc', items }], true); + } + clearSigns() { + let { nvim, signIds, bufnr } = this; + if (signIds.size > 0) { + nvim.call('coc#util#unplace_signs', [bufnr, Array.from(signIds)], true); + signIds.clear(); + } + } + async checkSigns() { + let { nvim, bufnr, signIds } = this; + try { + let content = await this.nvim.call('execute', [`sign place buffer=${bufnr}`]); + let lines = content.split('\n'); + let ids = []; + for (let line of lines) { + let ms = line.match(/^\s*line=\d+\s+id=(\d+)\s+name=(\w+)/); + if (!ms) + continue; + let [, id, name] = ms; + if (!signIds.has(Number(id)) && severityNames.indexOf(name) != -1) { + ids.push(id); + } + } + await nvim.call('coc#util#unplace_signs', [bufnr, ids]); + } + catch (e) { + // noop + } + } + addSigns(diagnostics) { + if (!this.config.enableSign && !this.config.enableHighlightLineNumber) + return; + this.clearSigns(); + let { nvim, bufnr, signIds } = this; + let signId = this.config.signOffset; + signIds.clear(); + let lines = new Set(); + for (let diagnostic of diagnostics) { + let { range, severity } = diagnostic; + let line = range.start.line; + if (lines.has(line)) + continue; + lines.add(line); + let name = util_1.getNameFromSeverity(severity); + nvim.command(`sign place ${signId} line=${line + 1} name=${name} buffer=${bufnr}`, true); + signIds.add(signId); + signId = signId + 1; + } + } + setDiagnosticInfo(bufnr, diagnostics) { + let lnums = [0, 0, 0, 0]; + let info = { error: 0, warning: 0, information: 0, hint: 0, lnums }; + for (let diagnostic of diagnostics) { + switch (diagnostic.severity) { + case vscode_languageserver_protocol_1.DiagnosticSeverity.Warning: + info.warning = info.warning + 1; + lnums[1] = lnums[1] || diagnostic.range.start.line + 1; + break; + case vscode_languageserver_protocol_1.DiagnosticSeverity.Information: + info.information = info.information + 1; + lnums[2] = lnums[2] || diagnostic.range.start.line + 1; + break; + case vscode_languageserver_protocol_1.DiagnosticSeverity.Hint: + info.hint = info.hint + 1; + lnums[3] = lnums[3] || diagnostic.range.start.line + 1; + break; + default: + lnums[0] = lnums[0] || diagnostic.range.start.line + 1; + info.error = info.error + 1; + } + } + this.nvim.call('coc#util#set_buf_var', [this.bufnr, 'coc_diagnostic_info', info], true); + if (bufnr == this.bufnr) { + this.nvim.call('coc#util#do_autocmd', ['CocDiagnosticChange'], true); + } + } + addDiagnosticVText(diagnostics) { + let { bufnr, nvim } = this; + if (!this.config.virtualText) + return; + if (!nvim.hasFunction('nvim_buf_set_virtual_text')) + return; + let buffer = this.nvim.createBuffer(bufnr); + let lines = new Set(); + let srcId = this.config.virtualTextSrcId; + let prefix = this.config.virtualTextPrefix; + buffer.clearNamespace(srcId); + for (let diagnostic of diagnostics) { + let { line } = diagnostic.range.start; + if (lines.has(line)) + continue; + lines.add(line); + let highlight = util_1.getNameFromSeverity(diagnostic.severity) + 'VirtualText'; + let msg = diagnostic.message.split(/\n/) + .map((l) => l.trim()) + .filter((l) => l.length > 0) + .slice(0, this.config.virtualTextLines) + .join(this.config.virtualTextLineSeparator); + buffer.setVirtualText(srcId, line, [[prefix + msg, highlight]], {}).logError(); + } + } + clearHighlight() { + let { matchIds } = this; + if (!this.document) + return; + this.document.clearMatchIds(matchIds); + this.matchIds.clear(); + } + addHighlight(diagnostics, winid) { + this.clearHighlight(); + if (diagnostics.length == 0) + return; + if (winid == -1 && workspace_1.default.isVim && !workspace_1.default.env.textprop) + return; + const highlights = new Map(); + for (let diagnostic of diagnostics) { + let { range, severity } = diagnostic; + let hlGroup = util_1.getNameFromSeverity(severity) + 'Highlight'; + let ranges = highlights.get(hlGroup) || []; + ranges.push(range); + highlights.set(hlGroup, ranges); + } + for (let [hlGroup, ranges] of highlights.entries()) { + let matchIds = this.document.highlightRanges(ranges, hlGroup, this.srdId); + for (let id of matchIds) + this.matchIds.add(id); + } + } + // fix range out of total characters + fixRange(range) { + let { start, end } = range; + if (start.line != end.line) + return range; + let line = this.document.getline(start.line); + if (!line) + return range; + if (start.character < line.length) + return range; + return vscode_languageserver_protocol_1.Range.create(start.line, line.length - 1, start.line, line.length); + } + /** + * Used on buffer unload + * + * @public + * @returns {Promise} + */ + async clear() { + if (this.sequence) + this.sequence.cancel().logError(); + let { nvim } = this; + nvim.pauseNotification(); + this.clearHighlight(); + this.clearSigns(); + if (this.config.virtualText + && nvim.hasFunction('nvim_buf_set_virtual_text') + && this.document) { + this.document.buffer.clearNamespace(this.config.virtualTextSrcId); + } + this.setDiagnosticInfo(workspace_1.default.bufnr, []); + await nvim.resumeNotification(false, true); + } + dispose() { + if (this.sequence) { + this.sequence.cancel().logError(); + } + this._onDidRefresh.dispose(); + } + get document() { + if (!this.bufnr) + return null; + return workspace_1.default.getDocument(this.bufnr); + } + get uri() { + if (!this.document) + return null; + return this.document.uri; + } + get nvim() { + return workspace_1.default.nvim; + } +} +exports.DiagnosticBuffer = DiagnosticBuffer; +//# sourceMappingURL=buffer.js.map + +/***/ }), +/* 402 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +class CallSequence { + constructor() { + this.funcs = new Set(); + this._canceled = false; + this._resolved = false; + } + addFunction(fn) { + this.funcs.add(fn); + } + start() { + this.promise = new Promise(async (resolve, reject) => { + for (let fn of this.funcs) { + if (this._canceled) + return resolve(true); + try { + let cancel = await Promise.resolve(fn()); + if (cancel === true) { + this._canceled = true; + return resolve(true); + } + } + catch (e) { + reject(e); + return; + } + } + this._resolved = true; + resolve(false); + }); + return this.promise; + } + ready() { + return this.promise; + } + cancel() { + if (this._resolved) + return Promise.resolve(void 0); + if (this._canceled) + return this.promise; + this._canceled = true; + return this.promise; + } +} +exports.default = CallSequence; +//# sourceMappingURL=callSequence.js.map + +/***/ }), +/* 403 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const vscode_languageserver_protocol_1 = __webpack_require__(150); +function getSeverityName(severity) { + switch (severity) { + case vscode_languageserver_protocol_1.DiagnosticSeverity.Error: + return 'Error'; + case vscode_languageserver_protocol_1.DiagnosticSeverity.Warning: + return 'Warning'; + case vscode_languageserver_protocol_1.DiagnosticSeverity.Information: + return 'Information'; + case vscode_languageserver_protocol_1.DiagnosticSeverity.Hint: + return 'Hint'; + default: + return 'Error'; + } +} +exports.getSeverityName = getSeverityName; +function getSeverityType(severity) { + switch (severity) { + case vscode_languageserver_protocol_1.DiagnosticSeverity.Error: + return 'E'; + case vscode_languageserver_protocol_1.DiagnosticSeverity.Warning: + return 'W'; + case vscode_languageserver_protocol_1.DiagnosticSeverity.Information: + return 'I'; + case vscode_languageserver_protocol_1.DiagnosticSeverity.Hint: + return 'I'; + default: + return 'Error'; + } +} +exports.getSeverityType = getSeverityType; +function severityLevel(level) { + switch (level) { + case 'hint': + return vscode_languageserver_protocol_1.DiagnosticSeverity.Hint; + case 'information': + return vscode_languageserver_protocol_1.DiagnosticSeverity.Information; + case 'warning': + return vscode_languageserver_protocol_1.DiagnosticSeverity.Warning; + case 'error': + return vscode_languageserver_protocol_1.DiagnosticSeverity.Error; + default: + return vscode_languageserver_protocol_1.DiagnosticSeverity.Hint; + } +} +exports.severityLevel = severityLevel; +function getNameFromSeverity(severity) { + switch (severity) { + case vscode_languageserver_protocol_1.DiagnosticSeverity.Error: + return 'CocError'; + case vscode_languageserver_protocol_1.DiagnosticSeverity.Warning: + return 'CocWarning'; + case vscode_languageserver_protocol_1.DiagnosticSeverity.Information: + return 'CocInfo'; + case vscode_languageserver_protocol_1.DiagnosticSeverity.Hint: + return 'CocHint'; + default: + return 'CocError'; + } +} +exports.getNameFromSeverity = getNameFromSeverity; +function getLocationListItem(owner, bufnr, diagnostic) { + let { start } = diagnostic.range; + let msg = diagnostic.message.split('\n')[0]; + let type = getSeverityName(diagnostic.severity).slice(0, 1).toUpperCase(); + return { + bufnr, + lnum: start.line + 1, + col: start.character + 1, + text: `[${owner}${diagnostic.code ? ' ' + diagnostic.code : ''}] ${msg} [${type}]`, + type + }; +} +exports.getLocationListItem = getLocationListItem; +//# sourceMappingURL=util.js.map + +/***/ }), +/* 404 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const vscode_languageserver_protocol_1 = __webpack_require__(150); +const vscode_uri_1 = __webpack_require__(183); +const position_1 = __webpack_require__(216); +const logger = __webpack_require__(2)('diagnostic-collection'); +class Collection { + constructor(owner) { + this.diagnosticsMap = new Map(); + this._onDispose = new vscode_languageserver_protocol_1.Emitter(); + this._onDidDiagnosticsChange = new vscode_languageserver_protocol_1.Emitter(); + this._onDidDiagnosticsClear = new vscode_languageserver_protocol_1.Emitter(); + this.onDispose = this._onDispose.event; + this.onDidDiagnosticsChange = this._onDidDiagnosticsChange.event; + this.onDidDiagnosticsClear = this._onDidDiagnosticsClear.event; + this.name = owner; + } + set(entries, diagnostics) { + if (Array.isArray(entries)) { + let map = new Map(); + for (let item of entries) { + let [file, diagnostics] = item; + let exists = map.get(file) || []; + if (diagnostics != null) { + for (let diagnostic of diagnostics) { + exists.push(diagnostic); + } + } + else { + exists = []; + } + map.set(file, exists); + } + for (let key of map.keys()) { + this.set(key, map.get(key)); + } + return; + } + let uri = entries; + uri = vscode_uri_1.URI.parse(uri).toString(); + if (diagnostics) { + diagnostics.forEach(o => { + let { range } = o; + range.start = range.start || vscode_languageserver_protocol_1.Position.create(0, 0); + range.end = range.end || vscode_languageserver_protocol_1.Position.create(1, 0); + if (position_1.emptyRange(range)) { + o.range.end = { + line: o.range.end.line, + character: o.range.end.character + 1 + }; + } + o.source = o.source || this.name; + }); + } + this.diagnosticsMap.set(uri, diagnostics || []); + this._onDidDiagnosticsChange.fire(uri); + return; + } + delete(uri) { + this.diagnosticsMap.delete(uri); + this._onDidDiagnosticsChange.fire(uri); + } + clear() { + let uris = Array.from(this.diagnosticsMap.keys()); + this.diagnosticsMap.clear(); + this._onDidDiagnosticsClear.fire(uris); + } + forEach(callback, thisArg) { + for (let uri of this.diagnosticsMap.keys()) { + let diagnostics = this.diagnosticsMap.get(uri); + callback.call(thisArg, uri, diagnostics, this); + } + } + get(uri) { + let arr = this.diagnosticsMap.get(uri); + return arr == null ? [] : arr; + } + has(uri) { + return this.diagnosticsMap.has(uri); + } + dispose() { + this.clear(); + this._onDispose.fire(void 0); + this._onDispose.dispose(); + this._onDidDiagnosticsClear.dispose(); + this._onDidDiagnosticsChange.dispose(); + } +} +exports.default = Collection; +//# sourceMappingURL=collection.js.map + /***/ }), /* 405 */ /***/ (function(module, exports, __webpack_require__) { @@ -65094,15 +65094,15 @@ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const vscode_languageserver_protocol_1 = __webpack_require__(150); const commands_1 = tslib_1.__importDefault(__webpack_require__(247)); -const manager_1 = tslib_1.__importDefault(__webpack_require__(319)); +const manager_1 = tslib_1.__importDefault(__webpack_require__(248)); const events_1 = tslib_1.__importDefault(__webpack_require__(149)); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); -const manager_2 = tslib_1.__importDefault(__webpack_require__(370)); -const floatFactory_1 = tslib_1.__importDefault(__webpack_require__(320)); -const services_1 = tslib_1.__importDefault(__webpack_require__(354)); -const manager_3 = tslib_1.__importDefault(__webpack_require__(248)); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); +const manager_2 = tslib_1.__importDefault(__webpack_require__(365)); +const floatFactory_1 = tslib_1.__importDefault(__webpack_require__(249)); +const services_1 = tslib_1.__importDefault(__webpack_require__(349)); +const manager_3 = tslib_1.__importDefault(__webpack_require__(250)); const util_1 = __webpack_require__(177); -const convert_1 = __webpack_require__(385); +const convert_1 = __webpack_require__(380); const object_1 = __webpack_require__(193); const position_1 = __webpack_require__(216); const string_1 = __webpack_require__(213); @@ -66408,8 +66408,8 @@ const tslib_1 = __webpack_require__(3); const debounce_1 = tslib_1.__importDefault(__webpack_require__(179)); const commands_1 = tslib_1.__importDefault(__webpack_require__(247)); const events_1 = tslib_1.__importDefault(__webpack_require__(149)); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); -const services_1 = tslib_1.__importDefault(__webpack_require__(354)); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); +const services_1 = tslib_1.__importDefault(__webpack_require__(349)); const util_1 = __webpack_require__(177); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); const logger = __webpack_require__(2)('codelens'); @@ -66672,7 +66672,7 @@ const tslib_1 = __webpack_require__(3); const debounce_1 = tslib_1.__importDefault(__webpack_require__(179)); const vscode_languageserver_protocol_1 = __webpack_require__(150); const events_1 = tslib_1.__importDefault(__webpack_require__(149)); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); const util_1 = __webpack_require__(177); const object_1 = __webpack_require__(193); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); @@ -66715,7 +66715,7 @@ class Colors { this.highlighters.delete(bufnr); } }, null, this.disposables); - workspace_1.default.onDidChangeTextDocument(async ({ textDocument, contentChanges }) => { + workspace_1.default.onDidChangeTextDocument(async ({ textDocument }) => { if (workspace_1.default.insertMode) return; let doc = workspace_1.default.getDocument(textDocument.uri); @@ -67027,7 +67027,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(3); const events_1 = tslib_1.__importDefault(__webpack_require__(149)); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); -const languages_1 = tslib_1.__importDefault(__webpack_require__(318)); +const languages_1 = tslib_1.__importDefault(__webpack_require__(320)); const vscode_languageserver_protocol_1 = __webpack_require__(150); const util_1 = __webpack_require__(177); const logger = __webpack_require__(2)('documentHighlight'); @@ -67131,7 +67131,7 @@ const path_1 = tslib_1.__importDefault(__webpack_require__(20)); const vscode_languageserver_types_1 = __webpack_require__(162); const vscode_uri_1 = __webpack_require__(183); const commands_1 = tslib_1.__importDefault(__webpack_require__(247)); -const highligher_1 = tslib_1.__importDefault(__webpack_require__(352)); +const highligher_1 = tslib_1.__importDefault(__webpack_require__(347)); const util_1 = __webpack_require__(177); const fs_1 = __webpack_require__(203); const object_1 = __webpack_require__(193); @@ -67811,8 +67811,8 @@ const path_1 = tslib_1.__importDefault(__webpack_require__(20)); const readline_1 = tslib_1.__importDefault(__webpack_require__(145)); const vscode_languageserver_types_1 = __webpack_require__(162); const which_1 = tslib_1.__importDefault(__webpack_require__(184)); -const highligher_1 = tslib_1.__importDefault(__webpack_require__(352)); -const ansiparse_1 = __webpack_require__(353); +const highligher_1 = tslib_1.__importDefault(__webpack_require__(347)); +const ansiparse_1 = __webpack_require__(348); const workspace_1 = tslib_1.__importDefault(__webpack_require__(190)); const logger = __webpack_require__(2)('handler-search'); const defaultArgs = ['--color', 'ansi', '--colors', 'path:fg:black', '--colors', 'line:fg:green', '--colors', 'match:fg:red', '--no-messages', '--heading', '-n']; @@ -68069,7 +68069,7 @@ exports.Mutex = Mutex; /* 415 */ /***/ (function(module) { -module.exports = JSON.parse("{\"name\":\"coc.nvim\",\"version\":\"0.0.75\",\"description\":\"LSP based intellisense engine for neovim & vim8.\",\"main\":\"./lib/index.js\",\"bin\":\"./bin/server.js\",\"scripts\":{\"clean\":\"rimraf lib build\",\"lint\":\"tslint -c tslint.json -p .\",\"build\":\"tsc -p tsconfig.json\",\"watch\":\"tsc -p tsconfig.json --watch true --sourceMap\",\"test\":\"node --trace-warnings node_modules/jest/bin/jest.js --runInBand --detectOpenHandles --forceExit\",\"test-build\":\"node --trace-warnings node_modules/jest/bin/jest.js --runInBand --coverage --forceExit\",\"prepare\":\"npm-run-all clean build\"},\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/neoclide/coc.nvim.git\"},\"keywords\":[\"complete\",\"neovim\"],\"author\":\"Qiming Zhao \",\"license\":\"MIT\",\"bugs\":{\"url\":\"https://github.com/neoclide/coc.nvim/issues\"},\"homepage\":\"https://github.com/neoclide/coc.nvim#readme\",\"jest\":{\"globals\":{\"__TEST__\":true},\"watchman\":false,\"clearMocks\":true,\"globalSetup\":\"./jest.js\",\"testEnvironment\":\"node\",\"moduleFileExtensions\":[\"ts\",\"tsx\",\"json\",\"js\"],\"transform\":{\"^.+\\\\.tsx?$\":\"ts-jest\"},\"testRegex\":\"src/__tests__/.*\\\\.(test|spec)\\\\.ts$\",\"coverageDirectory\":\"./coverage/\"},\"devDependencies\":{\"@chemzqm/tslint-config\":\"^1.0.18\",\"@types/debounce\":\"^3.0.0\",\"@types/fb-watchman\":\"^2.0.0\",\"@types/glob\":\"^7.1.1\",\"@types/jest\":\"^24.0.18\",\"@types/minimatch\":\"^3.0.3\",\"@types/mkdirp\":\"^0.5.2\",\"@types/node\":\"^12.12.17\",\"@types/semver\":\"^6.0.2\",\"@types/tar\":\"^4.0.3\",\"@types/tunnel\":\"^0.0.1\",\"@types/uuid\":\"^3.4.5\",\"@types/which\":\"^1.3.1\",\"colors\":\"^1.3.3\",\"jest\":\"24.9.0\",\"npm-run-all\":\"^4.1.5\",\"ts-jest\":\"^24.2.0\",\"tslint\":\"^5.19.0\",\"typescript\":\"^3.8.2\",\"vscode-languageserver\":\"^6.1.1\"},\"dependencies\":{\"@chemzqm/neovim\":\"5.1.9\",\"await-semaphore\":\"^0.1.3\",\"bser\":\"^2.1.0\",\"debounce\":\"^1.2.0\",\"fast-diff\":\"^1.2.0\",\"fb-watchman\":\"^2.0.0\",\"follow-redirects\":\"^1.9.0\",\"glob\":\"^7.1.4\",\"isuri\":\"^2.0.3\",\"jsonc-parser\":\"^2.1.1\",\"log4js\":\"^5.1.0\",\"minimatch\":\"^3.0.4\",\"mkdirp\":\"^0.5.1\",\"mv\":\"^2.1.1\",\"rc\":\"^1.2.8\",\"rimraf\":\"^3.0.0\",\"semver\":\"^6.3.0\",\"tar\":\"^4.4.10\",\"tslib\":\"^1.11.0\",\"tunnel\":\"^0.0.6\",\"uuid\":\"^3.3.3\",\"vscode-languageserver-protocol\":\"^3.15.3\",\"vscode-languageserver-types\":\"^3.15.1\",\"vscode-uri\":\"^2.0.3\",\"which\":\"^1.3.1\"}}"); +module.exports = JSON.parse("{\"name\":\"coc.nvim\",\"version\":\"0.0.76\",\"description\":\"LSP based intellisense engine for neovim & vim8.\",\"main\":\"./lib/index.js\",\"bin\":\"./bin/server.js\",\"scripts\":{\"clean\":\"rimraf lib build\",\"lint\":\"tslint -c tslint.json -p .\",\"build\":\"tsc -p tsconfig.json\",\"watch\":\"tsc -p tsconfig.json --watch true --sourceMap\",\"test\":\"node --trace-warnings node_modules/jest/bin/jest.js --runInBand --detectOpenHandles --forceExit\",\"test-build\":\"node --trace-warnings node_modules/jest/bin/jest.js --runInBand --coverage --forceExit\",\"prepare\":\"npm-run-all clean build\"},\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/neoclide/coc.nvim.git\"},\"keywords\":[\"complete\",\"neovim\"],\"author\":\"Qiming Zhao \",\"license\":\"MIT\",\"bugs\":{\"url\":\"https://github.com/neoclide/coc.nvim/issues\"},\"homepage\":\"https://github.com/neoclide/coc.nvim#readme\",\"jest\":{\"globals\":{\"__TEST__\":true},\"watchman\":false,\"clearMocks\":true,\"globalSetup\":\"./jest.js\",\"testEnvironment\":\"node\",\"moduleFileExtensions\":[\"ts\",\"tsx\",\"json\",\"js\"],\"transform\":{\"^.+\\\\.tsx?$\":\"ts-jest\"},\"testRegex\":\"src/__tests__/.*\\\\.(test|spec)\\\\.ts$\",\"coverageDirectory\":\"./coverage/\"},\"devDependencies\":{\"@chemzqm/tslint-config\":\"^1.0.18\",\"@types/debounce\":\"^3.0.0\",\"@types/fb-watchman\":\"^2.0.0\",\"@types/glob\":\"^7.1.1\",\"@types/jest\":\"^24.0.18\",\"@types/minimatch\":\"^3.0.3\",\"@types/mkdirp\":\"^0.5.2\",\"@types/node\":\"^12.12.17\",\"@types/semver\":\"^6.0.2\",\"@types/tar\":\"^4.0.3\",\"@types/tunnel\":\"^0.0.1\",\"@types/uuid\":\"^3.4.5\",\"@types/which\":\"^1.3.1\",\"colors\":\"^1.3.3\",\"jest\":\"24.9.0\",\"npm-run-all\":\"^4.1.5\",\"ts-jest\":\"^24.2.0\",\"tslint\":\"^5.19.0\",\"typescript\":\"^3.8.2\",\"vscode-languageserver\":\"^6.1.1\"},\"dependencies\":{\"@chemzqm/neovim\":\"5.1.9\",\"await-semaphore\":\"^0.1.3\",\"bser\":\"^2.1.0\",\"debounce\":\"^1.2.0\",\"fast-diff\":\"^1.2.0\",\"fb-watchman\":\"^2.0.0\",\"follow-redirects\":\"^1.9.0\",\"glob\":\"^7.1.4\",\"isuri\":\"^2.0.3\",\"jsonc-parser\":\"^2.1.1\",\"log4js\":\"^5.1.0\",\"minimatch\":\"^3.0.4\",\"mkdirp\":\"^0.5.1\",\"mv\":\"^2.1.1\",\"rc\":\"^1.2.8\",\"rimraf\":\"^3.0.0\",\"semver\":\"^6.3.0\",\"tar\":\"^4.4.10\",\"tslib\":\"^1.11.0\",\"tunnel\":\"^0.0.6\",\"uuid\":\"^3.3.3\",\"vscode-languageserver-protocol\":\"^3.15.3\",\"vscode-languageserver-types\":\"^3.15.1\",\"vscode-uri\":\"^2.0.3\",\"which\":\"^1.3.1\"}}"); /***/ }) /******/ ]); \ No newline at end of file diff --git a/package.json b/package.json index 46591338fbd..3cfec043fe1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "coc.nvim", - "version": "0.0.75", + "version": "0.0.76", "description": "LSP based intellisense engine for neovim & vim8.", "main": "./lib/index.js", "bin": "./bin/server.js",