67150 lines
2.1 MiB
67150 lines
2.1 MiB
/******/ (function(modules) { // webpackBootstrap
|
|
/******/ // The module cache
|
|
/******/ var installedModules = {};
|
|
/******/
|
|
/******/ // The require function
|
|
/******/ function __webpack_require__(moduleId) {
|
|
/******/
|
|
/******/ // Check if module is in cache
|
|
/******/ if(installedModules[moduleId]) {
|
|
/******/ return installedModules[moduleId].exports;
|
|
/******/ }
|
|
/******/ // Create a new module (and put it into the cache)
|
|
/******/ var module = installedModules[moduleId] = {
|
|
/******/ i: moduleId,
|
|
/******/ l: false,
|
|
/******/ exports: {}
|
|
/******/ };
|
|
/******/
|
|
/******/ // Execute the module function
|
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
/******/
|
|
/******/ // Flag the module as loaded
|
|
/******/ module.l = true;
|
|
/******/
|
|
/******/ // Return the exports of the module
|
|
/******/ return module.exports;
|
|
/******/ }
|
|
/******/
|
|
/******/
|
|
/******/ // expose the modules object (__webpack_modules__)
|
|
/******/ __webpack_require__.m = modules;
|
|
/******/
|
|
/******/ // expose the module cache
|
|
/******/ __webpack_require__.c = installedModules;
|
|
/******/
|
|
/******/ // define getter function for harmony exports
|
|
/******/ __webpack_require__.d = function(exports, name, getter) {
|
|
/******/ if(!__webpack_require__.o(exports, name)) {
|
|
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
|
/******/ }
|
|
/******/ };
|
|
/******/
|
|
/******/ // define __esModule on exports
|
|
/******/ __webpack_require__.r = function(exports) {
|
|
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
/******/ }
|
|
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
/******/ };
|
|
/******/
|
|
/******/ // create a fake namespace object
|
|
/******/ // mode & 1: value is a module id, require it
|
|
/******/ // mode & 2: merge all properties of value into the ns
|
|
/******/ // mode & 4: return value when already ns object
|
|
/******/ // mode & 8|1: behave like require
|
|
/******/ __webpack_require__.t = function(value, mode) {
|
|
/******/ if(mode & 1) value = __webpack_require__(value);
|
|
/******/ if(mode & 8) return value;
|
|
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
|
/******/ var ns = Object.create(null);
|
|
/******/ __webpack_require__.r(ns);
|
|
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
|
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
|
/******/ return ns;
|
|
/******/ };
|
|
/******/
|
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
/******/ __webpack_require__.n = function(module) {
|
|
/******/ var getter = module && module.__esModule ?
|
|
/******/ function getDefault() { return module['default']; } :
|
|
/******/ function getModuleExports() { return module; };
|
|
/******/ __webpack_require__.d(getter, 'a', getter);
|
|
/******/ return getter;
|
|
/******/ };
|
|
/******/
|
|
/******/ // Object.prototype.hasOwnProperty.call
|
|
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
|
/******/
|
|
/******/ // __webpack_public_path__
|
|
/******/ __webpack_require__.p = "";
|
|
/******/
|
|
/******/
|
|
/******/ // Load entry module and return exports
|
|
/******/ return __webpack_require__(__webpack_require__.s = 0);
|
|
/******/ })
|
|
/************************************************************************/
|
|
/******/ ([
|
|
/* 0 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const semver = __webpack_require__(1)
|
|
const version = process.version.replace('v', '')
|
|
if (!semver.gte(version, '8.10.0')) {
|
|
console.error('node version ' + version + ' < 8.10.0, please upgrade nodejs, or use `let g:coc_node_path = "/path/to/node"` in your vimrc')
|
|
process.exit()
|
|
}
|
|
Object.defineProperty(console, 'log', {
|
|
value: () => { }
|
|
})
|
|
const attach = __webpack_require__(2).default
|
|
const logger = __webpack_require__(186)('server')
|
|
|
|
attach({ reader: process.stdin, writer: process.stdout })
|
|
|
|
process.on('uncaughtException', function (err) {
|
|
let msg = 'Uncaught exception: ' + err.stack
|
|
console.error(msg)
|
|
logger.error('uncaughtException', err.stack)
|
|
})
|
|
|
|
process.on('unhandledRejection', function (reason, p) {
|
|
if (reason instanceof Error) {
|
|
console.error('UnhandledRejection: ' + reason.message + '\n' + reason.stack)
|
|
} else {
|
|
console.error('UnhandledRejection: ' + reason)
|
|
}
|
|
logger.error('unhandledRejection ', p, reason)
|
|
})
|
|
|
|
|
|
/***/ }),
|
|
/* 1 */
|
|
/***/ (function(module, exports) {
|
|
|
|
exports = module.exports = SemVer
|
|
|
|
var debug
|
|
/* istanbul ignore next */
|
|
if (typeof process === 'object' &&
|
|
process.env &&
|
|
process.env.NODE_DEBUG &&
|
|
/\bsemver\b/i.test(process.env.NODE_DEBUG)) {
|
|
debug = function () {
|
|
var args = Array.prototype.slice.call(arguments, 0)
|
|
args.unshift('SEMVER')
|
|
console.log.apply(console, args)
|
|
}
|
|
} else {
|
|
debug = function () {}
|
|
}
|
|
|
|
// Note: this is the semver.org version of the spec that it implements
|
|
// Not necessarily the package version of this code.
|
|
exports.SEMVER_SPEC_VERSION = '2.0.0'
|
|
|
|
var MAX_LENGTH = 256
|
|
var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
|
|
/* istanbul ignore next */ 9007199254740991
|
|
|
|
// Max safe segment length for coercion.
|
|
var MAX_SAFE_COMPONENT_LENGTH = 16
|
|
|
|
// The actual regexps go on exports.re
|
|
var re = exports.re = []
|
|
var src = exports.src = []
|
|
var t = exports.tokens = {}
|
|
var R = 0
|
|
|
|
function tok (n) {
|
|
t[n] = R++
|
|
}
|
|
|
|
// The following Regular Expressions can be used for tokenizing,
|
|
// validating, and parsing SemVer version strings.
|
|
|
|
// ## Numeric Identifier
|
|
// A single `0`, or a non-zero digit followed by zero or more digits.
|
|
|
|
tok('NUMERICIDENTIFIER')
|
|
src[t.NUMERICIDENTIFIER] = '0|[1-9]\\d*'
|
|
tok('NUMERICIDENTIFIERLOOSE')
|
|
src[t.NUMERICIDENTIFIERLOOSE] = '[0-9]+'
|
|
|
|
// ## Non-numeric Identifier
|
|
// Zero or more digits, followed by a letter or hyphen, and then zero or
|
|
// more letters, digits, or hyphens.
|
|
|
|
tok('NONNUMERICIDENTIFIER')
|
|
src[t.NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'
|
|
|
|
// ## Main Version
|
|
// Three dot-separated numeric identifiers.
|
|
|
|
tok('MAINVERSION')
|
|
src[t.MAINVERSION] = '(' + src[t.NUMERICIDENTIFIER] + ')\\.' +
|
|
'(' + src[t.NUMERICIDENTIFIER] + ')\\.' +
|
|
'(' + src[t.NUMERICIDENTIFIER] + ')'
|
|
|
|
tok('MAINVERSIONLOOSE')
|
|
src[t.MAINVERSIONLOOSE] = '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')\\.' +
|
|
'(' + src[t.NUMERICIDENTIFIERLOOSE] + ')\\.' +
|
|
'(' + src[t.NUMERICIDENTIFIERLOOSE] + ')'
|
|
|
|
// ## Pre-release Version Identifier
|
|
// A numeric identifier, or a non-numeric identifier.
|
|
|
|
tok('PRERELEASEIDENTIFIER')
|
|
src[t.PRERELEASEIDENTIFIER] = '(?:' + src[t.NUMERICIDENTIFIER] +
|
|
'|' + src[t.NONNUMERICIDENTIFIER] + ')'
|
|
|
|
tok('PRERELEASEIDENTIFIERLOOSE')
|
|
src[t.PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[t.NUMERICIDENTIFIERLOOSE] +
|
|
'|' + src[t.NONNUMERICIDENTIFIER] + ')'
|
|
|
|
// ## Pre-release Version
|
|
// Hyphen, followed by one or more dot-separated pre-release version
|
|
// identifiers.
|
|
|
|
tok('PRERELEASE')
|
|
src[t.PRERELEASE] = '(?:-(' + src[t.PRERELEASEIDENTIFIER] +
|
|
'(?:\\.' + src[t.PRERELEASEIDENTIFIER] + ')*))'
|
|
|
|
tok('PRERELEASELOOSE')
|
|
src[t.PRERELEASELOOSE] = '(?:-?(' + src[t.PRERELEASEIDENTIFIERLOOSE] +
|
|
'(?:\\.' + src[t.PRERELEASEIDENTIFIERLOOSE] + ')*))'
|
|
|
|
// ## Build Metadata Identifier
|
|
// Any combination of digits, letters, or hyphens.
|
|
|
|
tok('BUILDIDENTIFIER')
|
|
src[t.BUILDIDENTIFIER] = '[0-9A-Za-z-]+'
|
|
|
|
// ## Build Metadata
|
|
// Plus sign, followed by one or more period-separated build metadata
|
|
// identifiers.
|
|
|
|
tok('BUILD')
|
|
src[t.BUILD] = '(?:\\+(' + src[t.BUILDIDENTIFIER] +
|
|
'(?:\\.' + src[t.BUILDIDENTIFIER] + ')*))'
|
|
|
|
// ## Full Version String
|
|
// A main version, followed optionally by a pre-release version and
|
|
// build metadata.
|
|
|
|
// Note that the only major, minor, patch, and pre-release sections of
|
|
// the version string are capturing groups. The build metadata is not a
|
|
// capturing group, because it should not ever be used in version
|
|
// comparison.
|
|
|
|
tok('FULL')
|
|
tok('FULLPLAIN')
|
|
src[t.FULLPLAIN] = 'v?' + src[t.MAINVERSION] +
|
|
src[t.PRERELEASE] + '?' +
|
|
src[t.BUILD] + '?'
|
|
|
|
src[t.FULL] = '^' + src[t.FULLPLAIN] + '$'
|
|
|
|
// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
|
|
// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
|
|
// common in the npm registry.
|
|
tok('LOOSEPLAIN')
|
|
src[t.LOOSEPLAIN] = '[v=\\s]*' + src[t.MAINVERSIONLOOSE] +
|
|
src[t.PRERELEASELOOSE] + '?' +
|
|
src[t.BUILD] + '?'
|
|
|
|
tok('LOOSE')
|
|
src[t.LOOSE] = '^' + src[t.LOOSEPLAIN] + '$'
|
|
|
|
tok('GTLT')
|
|
src[t.GTLT] = '((?:<|>)?=?)'
|
|
|
|
// Something like "2.*" or "1.2.x".
|
|
// Note that "x.x" is a valid xRange identifer, meaning "any version"
|
|
// Only the first item is strictly required.
|
|
tok('XRANGEIDENTIFIERLOOSE')
|
|
src[t.XRANGEIDENTIFIERLOOSE] = src[t.NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'
|
|
tok('XRANGEIDENTIFIER')
|
|
src[t.XRANGEIDENTIFIER] = src[t.NUMERICIDENTIFIER] + '|x|X|\\*'
|
|
|
|
tok('XRANGEPLAIN')
|
|
src[t.XRANGEPLAIN] = '[v=\\s]*(' + src[t.XRANGEIDENTIFIER] + ')' +
|
|
'(?:\\.(' + src[t.XRANGEIDENTIFIER] + ')' +
|
|
'(?:\\.(' + src[t.XRANGEIDENTIFIER] + ')' +
|
|
'(?:' + src[t.PRERELEASE] + ')?' +
|
|
src[t.BUILD] + '?' +
|
|
')?)?'
|
|
|
|
tok('XRANGEPLAINLOOSE')
|
|
src[t.XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' +
|
|
'(?:\\.(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' +
|
|
'(?:\\.(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' +
|
|
'(?:' + src[t.PRERELEASELOOSE] + ')?' +
|
|
src[t.BUILD] + '?' +
|
|
')?)?'
|
|
|
|
tok('XRANGE')
|
|
src[t.XRANGE] = '^' + src[t.GTLT] + '\\s*' + src[t.XRANGEPLAIN] + '$'
|
|
tok('XRANGELOOSE')
|
|
src[t.XRANGELOOSE] = '^' + src[t.GTLT] + '\\s*' + src[t.XRANGEPLAINLOOSE] + '$'
|
|
|
|
// Coercion.
|
|
// Extract anything that could conceivably be a part of a valid semver
|
|
tok('COERCE')
|
|
src[t.COERCE] = '(^|[^\\d])' +
|
|
'(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' +
|
|
'(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' +
|
|
'(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' +
|
|
'(?:$|[^\\d])'
|
|
tok('COERCERTL')
|
|
re[t.COERCERTL] = new RegExp(src[t.COERCE], 'g')
|
|
|
|
// Tilde ranges.
|
|
// Meaning is "reasonably at or greater than"
|
|
tok('LONETILDE')
|
|
src[t.LONETILDE] = '(?:~>?)'
|
|
|
|
tok('TILDETRIM')
|
|
src[t.TILDETRIM] = '(\\s*)' + src[t.LONETILDE] + '\\s+'
|
|
re[t.TILDETRIM] = new RegExp(src[t.TILDETRIM], 'g')
|
|
var tildeTrimReplace = '$1~'
|
|
|
|
tok('TILDE')
|
|
src[t.TILDE] = '^' + src[t.LONETILDE] + src[t.XRANGEPLAIN] + '$'
|
|
tok('TILDELOOSE')
|
|
src[t.TILDELOOSE] = '^' + src[t.LONETILDE] + src[t.XRANGEPLAINLOOSE] + '$'
|
|
|
|
// Caret ranges.
|
|
// Meaning is "at least and backwards compatible with"
|
|
tok('LONECARET')
|
|
src[t.LONECARET] = '(?:\\^)'
|
|
|
|
tok('CARETTRIM')
|
|
src[t.CARETTRIM] = '(\\s*)' + src[t.LONECARET] + '\\s+'
|
|
re[t.CARETTRIM] = new RegExp(src[t.CARETTRIM], 'g')
|
|
var caretTrimReplace = '$1^'
|
|
|
|
tok('CARET')
|
|
src[t.CARET] = '^' + src[t.LONECARET] + src[t.XRANGEPLAIN] + '$'
|
|
tok('CARETLOOSE')
|
|
src[t.CARETLOOSE] = '^' + src[t.LONECARET] + src[t.XRANGEPLAINLOOSE] + '$'
|
|
|
|
// A simple gt/lt/eq thing, or just "" to indicate "any version"
|
|
tok('COMPARATORLOOSE')
|
|
src[t.COMPARATORLOOSE] = '^' + src[t.GTLT] + '\\s*(' + src[t.LOOSEPLAIN] + ')$|^$'
|
|
tok('COMPARATOR')
|
|
src[t.COMPARATOR] = '^' + src[t.GTLT] + '\\s*(' + src[t.FULLPLAIN] + ')$|^$'
|
|
|
|
// An expression to strip any whitespace between the gtlt and the thing
|
|
// it modifies, so that `> 1.2.3` ==> `>1.2.3`
|
|
tok('COMPARATORTRIM')
|
|
src[t.COMPARATORTRIM] = '(\\s*)' + src[t.GTLT] +
|
|
'\\s*(' + src[t.LOOSEPLAIN] + '|' + src[t.XRANGEPLAIN] + ')'
|
|
|
|
// this one has to use the /g flag
|
|
re[t.COMPARATORTRIM] = new RegExp(src[t.COMPARATORTRIM], 'g')
|
|
var comparatorTrimReplace = '$1$2$3'
|
|
|
|
// Something like `1.2.3 - 1.2.4`
|
|
// Note that these all use the loose form, because they'll be
|
|
// checked against either the strict or loose comparator form
|
|
// later.
|
|
tok('HYPHENRANGE')
|
|
src[t.HYPHENRANGE] = '^\\s*(' + src[t.XRANGEPLAIN] + ')' +
|
|
'\\s+-\\s+' +
|
|
'(' + src[t.XRANGEPLAIN] + ')' +
|
|
'\\s*$'
|
|
|
|
tok('HYPHENRANGELOOSE')
|
|
src[t.HYPHENRANGELOOSE] = '^\\s*(' + src[t.XRANGEPLAINLOOSE] + ')' +
|
|
'\\s+-\\s+' +
|
|
'(' + src[t.XRANGEPLAINLOOSE] + ')' +
|
|
'\\s*$'
|
|
|
|
// Star ranges basically just allow anything at all.
|
|
tok('STAR')
|
|
src[t.STAR] = '(<|>)?=?\\s*\\*'
|
|
|
|
// Compile to actual regexp objects.
|
|
// All are flag-free, unless they were created above with a flag.
|
|
for (var i = 0; i < R; i++) {
|
|
debug(i, src[i])
|
|
if (!re[i]) {
|
|
re[i] = new RegExp(src[i])
|
|
}
|
|
}
|
|
|
|
exports.parse = parse
|
|
function parse (version, options) {
|
|
if (!options || typeof options !== 'object') {
|
|
options = {
|
|
loose: !!options,
|
|
includePrerelease: false
|
|
}
|
|
}
|
|
|
|
if (version instanceof SemVer) {
|
|
return version
|
|
}
|
|
|
|
if (typeof version !== 'string') {
|
|
return null
|
|
}
|
|
|
|
if (version.length > MAX_LENGTH) {
|
|
return null
|
|
}
|
|
|
|
var r = options.loose ? re[t.LOOSE] : re[t.FULL]
|
|
if (!r.test(version)) {
|
|
return null
|
|
}
|
|
|
|
try {
|
|
return new SemVer(version, options)
|
|
} catch (er) {
|
|
return null
|
|
}
|
|
}
|
|
|
|
exports.valid = valid
|
|
function valid (version, options) {
|
|
var v = parse(version, options)
|
|
return v ? v.version : null
|
|
}
|
|
|
|
exports.clean = clean
|
|
function clean (version, options) {
|
|
var s = parse(version.trim().replace(/^[=v]+/, ''), options)
|
|
return s ? s.version : null
|
|
}
|
|
|
|
exports.SemVer = SemVer
|
|
|
|
function SemVer (version, options) {
|
|
if (!options || typeof options !== 'object') {
|
|
options = {
|
|
loose: !!options,
|
|
includePrerelease: false
|
|
}
|
|
}
|
|
if (version instanceof SemVer) {
|
|
if (version.loose === options.loose) {
|
|
return version
|
|
} else {
|
|
version = version.version
|
|
}
|
|
} else if (typeof version !== 'string') {
|
|
throw new TypeError('Invalid Version: ' + version)
|
|
}
|
|
|
|
if (version.length > MAX_LENGTH) {
|
|
throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters')
|
|
}
|
|
|
|
if (!(this instanceof SemVer)) {
|
|
return new SemVer(version, options)
|
|
}
|
|
|
|
debug('SemVer', version, options)
|
|
this.options = options
|
|
this.loose = !!options.loose
|
|
|
|
var m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL])
|
|
|
|
if (!m) {
|
|
throw new TypeError('Invalid Version: ' + version)
|
|
}
|
|
|
|
this.raw = version
|
|
|
|
// these are actually numbers
|
|
this.major = +m[1]
|
|
this.minor = +m[2]
|
|
this.patch = +m[3]
|
|
|
|
if (this.major > MAX_SAFE_INTEGER || this.major < 0) {
|
|
throw new TypeError('Invalid major version')
|
|
}
|
|
|
|
if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) {
|
|
throw new TypeError('Invalid minor version')
|
|
}
|
|
|
|
if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) {
|
|
throw new TypeError('Invalid patch version')
|
|
}
|
|
|
|
// numberify any prerelease numeric ids
|
|
if (!m[4]) {
|
|
this.prerelease = []
|
|
} else {
|
|
this.prerelease = m[4].split('.').map(function (id) {
|
|
if (/^[0-9]+$/.test(id)) {
|
|
var num = +id
|
|
if (num >= 0 && num < MAX_SAFE_INTEGER) {
|
|
return num
|
|
}
|
|
}
|
|
return id
|
|
})
|
|
}
|
|
|
|
this.build = m[5] ? m[5].split('.') : []
|
|
this.format()
|
|
}
|
|
|
|
SemVer.prototype.format = function () {
|
|
this.version = this.major + '.' + this.minor + '.' + this.patch
|
|
if (this.prerelease.length) {
|
|
this.version += '-' + this.prerelease.join('.')
|
|
}
|
|
return this.version
|
|
}
|
|
|
|
SemVer.prototype.toString = function () {
|
|
return this.version
|
|
}
|
|
|
|
SemVer.prototype.compare = function (other) {
|
|
debug('SemVer.compare', this.version, this.options, other)
|
|
if (!(other instanceof SemVer)) {
|
|
other = new SemVer(other, this.options)
|
|
}
|
|
|
|
return this.compareMain(other) || this.comparePre(other)
|
|
}
|
|
|
|
SemVer.prototype.compareMain = function (other) {
|
|
if (!(other instanceof SemVer)) {
|
|
other = new SemVer(other, this.options)
|
|
}
|
|
|
|
return compareIdentifiers(this.major, other.major) ||
|
|
compareIdentifiers(this.minor, other.minor) ||
|
|
compareIdentifiers(this.patch, other.patch)
|
|
}
|
|
|
|
SemVer.prototype.comparePre = function (other) {
|
|
if (!(other instanceof SemVer)) {
|
|
other = new SemVer(other, this.options)
|
|
}
|
|
|
|
// NOT having a prerelease is > having one
|
|
if (this.prerelease.length && !other.prerelease.length) {
|
|
return -1
|
|
} else if (!this.prerelease.length && other.prerelease.length) {
|
|
return 1
|
|
} else if (!this.prerelease.length && !other.prerelease.length) {
|
|
return 0
|
|
}
|
|
|
|
var i = 0
|
|
do {
|
|
var a = this.prerelease[i]
|
|
var b = other.prerelease[i]
|
|
debug('prerelease compare', i, a, b)
|
|
if (a === undefined && b === undefined) {
|
|
return 0
|
|
} else if (b === undefined) {
|
|
return 1
|
|
} else if (a === undefined) {
|
|
return -1
|
|
} else if (a === b) {
|
|
continue
|
|
} else {
|
|
return compareIdentifiers(a, b)
|
|
}
|
|
} while (++i)
|
|
}
|
|
|
|
SemVer.prototype.compareBuild = function (other) {
|
|
if (!(other instanceof SemVer)) {
|
|
other = new SemVer(other, this.options)
|
|
}
|
|
|
|
var i = 0
|
|
do {
|
|
var a = this.build[i]
|
|
var b = other.build[i]
|
|
debug('prerelease compare', i, a, b)
|
|
if (a === undefined && b === undefined) {
|
|
return 0
|
|
} else if (b === undefined) {
|
|
return 1
|
|
} else if (a === undefined) {
|
|
return -1
|
|
} else if (a === b) {
|
|
continue
|
|
} else {
|
|
return compareIdentifiers(a, b)
|
|
}
|
|
} while (++i)
|
|
}
|
|
|
|
// preminor will bump the version up to the next minor release, and immediately
|
|
// down to pre-release. premajor and prepatch work the same way.
|
|
SemVer.prototype.inc = function (release, identifier) {
|
|
switch (release) {
|
|
case 'premajor':
|
|
this.prerelease.length = 0
|
|
this.patch = 0
|
|
this.minor = 0
|
|
this.major++
|
|
this.inc('pre', identifier)
|
|
break
|
|
case 'preminor':
|
|
this.prerelease.length = 0
|
|
this.patch = 0
|
|
this.minor++
|
|
this.inc('pre', identifier)
|
|
break
|
|
case 'prepatch':
|
|
// If this is already a prerelease, it will bump to the next version
|
|
// drop any prereleases that might already exist, since they are not
|
|
// relevant at this point.
|
|
this.prerelease.length = 0
|
|
this.inc('patch', identifier)
|
|
this.inc('pre', identifier)
|
|
break
|
|
// If the input is a non-prerelease version, this acts the same as
|
|
// prepatch.
|
|
case 'prerelease':
|
|
if (this.prerelease.length === 0) {
|
|
this.inc('patch', identifier)
|
|
}
|
|
this.inc('pre', identifier)
|
|
break
|
|
|
|
case 'major':
|
|
// If this is a pre-major version, bump up to the same major version.
|
|
// Otherwise increment major.
|
|
// 1.0.0-5 bumps to 1.0.0
|
|
// 1.1.0 bumps to 2.0.0
|
|
if (this.minor !== 0 ||
|
|
this.patch !== 0 ||
|
|
this.prerelease.length === 0) {
|
|
this.major++
|
|
}
|
|
this.minor = 0
|
|
this.patch = 0
|
|
this.prerelease = []
|
|
break
|
|
case 'minor':
|
|
// If this is a pre-minor version, bump up to the same minor version.
|
|
// Otherwise increment minor.
|
|
// 1.2.0-5 bumps to 1.2.0
|
|
// 1.2.1 bumps to 1.3.0
|
|
if (this.patch !== 0 || this.prerelease.length === 0) {
|
|
this.minor++
|
|
}
|
|
this.patch = 0
|
|
this.prerelease = []
|
|
break
|
|
case 'patch':
|
|
// If this is not a pre-release version, it will increment the patch.
|
|
// If it is a pre-release it will bump up to the same patch version.
|
|
// 1.2.0-5 patches to 1.2.0
|
|
// 1.2.0 patches to 1.2.1
|
|
if (this.prerelease.length === 0) {
|
|
this.patch++
|
|
}
|
|
this.prerelease = []
|
|
break
|
|
// This probably shouldn't be used publicly.
|
|
// 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction.
|
|
case 'pre':
|
|
if (this.prerelease.length === 0) {
|
|
this.prerelease = [0]
|
|
} else {
|
|
var i = this.prerelease.length
|
|
while (--i >= 0) {
|
|
if (typeof this.prerelease[i] === 'number') {
|
|
this.prerelease[i]++
|
|
i = -2
|
|
}
|
|
}
|
|
if (i === -1) {
|
|
// didn't increment anything
|
|
this.prerelease.push(0)
|
|
}
|
|
}
|
|
if (identifier) {
|
|
// 1.2.0-beta.1 bumps to 1.2.0-beta.2,
|
|
// 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
|
|
if (this.prerelease[0] === identifier) {
|
|
if (isNaN(this.prerelease[1])) {
|
|
this.prerelease = [identifier, 0]
|
|
}
|
|
} else {
|
|
this.prerelease = [identifier, 0]
|
|
}
|
|
}
|
|
break
|
|
|
|
default:
|
|
throw new Error('invalid increment argument: ' + release)
|
|
}
|
|
this.format()
|
|
this.raw = this.version
|
|
return this
|
|
}
|
|
|
|
exports.inc = inc
|
|
function inc (version, release, loose, identifier) {
|
|
if (typeof (loose) === 'string') {
|
|
identifier = loose
|
|
loose = undefined
|
|
}
|
|
|
|
try {
|
|
return new SemVer(version, loose).inc(release, identifier).version
|
|
} catch (er) {
|
|
return null
|
|
}
|
|
}
|
|
|
|
exports.diff = diff
|
|
function diff (version1, version2) {
|
|
if (eq(version1, version2)) {
|
|
return null
|
|
} else {
|
|
var v1 = parse(version1)
|
|
var v2 = parse(version2)
|
|
var prefix = ''
|
|
if (v1.prerelease.length || v2.prerelease.length) {
|
|
prefix = 'pre'
|
|
var defaultResult = 'prerelease'
|
|
}
|
|
for (var key in v1) {
|
|
if (key === 'major' || key === 'minor' || key === 'patch') {
|
|
if (v1[key] !== v2[key]) {
|
|
return prefix + key
|
|
}
|
|
}
|
|
}
|
|
return defaultResult // may be undefined
|
|
}
|
|
}
|
|
|
|
exports.compareIdentifiers = compareIdentifiers
|
|
|
|
var numeric = /^[0-9]+$/
|
|
function compareIdentifiers (a, b) {
|
|
var anum = numeric.test(a)
|
|
var bnum = numeric.test(b)
|
|
|
|
if (anum && bnum) {
|
|
a = +a
|
|
b = +b
|
|
}
|
|
|
|
return a === b ? 0
|
|
: (anum && !bnum) ? -1
|
|
: (bnum && !anum) ? 1
|
|
: a < b ? -1
|
|
: 1
|
|
}
|
|
|
|
exports.rcompareIdentifiers = rcompareIdentifiers
|
|
function rcompareIdentifiers (a, b) {
|
|
return compareIdentifiers(b, a)
|
|
}
|
|
|
|
exports.major = major
|
|
function major (a, loose) {
|
|
return new SemVer(a, loose).major
|
|
}
|
|
|
|
exports.minor = minor
|
|
function minor (a, loose) {
|
|
return new SemVer(a, loose).minor
|
|
}
|
|
|
|
exports.patch = patch
|
|
function patch (a, loose) {
|
|
return new SemVer(a, loose).patch
|
|
}
|
|
|
|
exports.compare = compare
|
|
function compare (a, b, loose) {
|
|
return new SemVer(a, loose).compare(new SemVer(b, loose))
|
|
}
|
|
|
|
exports.compareLoose = compareLoose
|
|
function compareLoose (a, b) {
|
|
return compare(a, b, true)
|
|
}
|
|
|
|
exports.compareBuild = compareBuild
|
|
function compareBuild (a, b, loose) {
|
|
var versionA = new SemVer(a, loose)
|
|
var versionB = new SemVer(b, loose)
|
|
return versionA.compare(versionB) || versionA.compareBuild(versionB)
|
|
}
|
|
|
|
exports.rcompare = rcompare
|
|
function rcompare (a, b, loose) {
|
|
return compare(b, a, loose)
|
|
}
|
|
|
|
exports.sort = sort
|
|
function sort (list, loose) {
|
|
return list.sort(function (a, b) {
|
|
return exports.compareBuild(a, b, loose)
|
|
})
|
|
}
|
|
|
|
exports.rsort = rsort
|
|
function rsort (list, loose) {
|
|
return list.sort(function (a, b) {
|
|
return exports.compareBuild(b, a, loose)
|
|
})
|
|
}
|
|
|
|
exports.gt = gt
|
|
function gt (a, b, loose) {
|
|
return compare(a, b, loose) > 0
|
|
}
|
|
|
|
exports.lt = lt
|
|
function lt (a, b, loose) {
|
|
return compare(a, b, loose) < 0
|
|
}
|
|
|
|
exports.eq = eq
|
|
function eq (a, b, loose) {
|
|
return compare(a, b, loose) === 0
|
|
}
|
|
|
|
exports.neq = neq
|
|
function neq (a, b, loose) {
|
|
return compare(a, b, loose) !== 0
|
|
}
|
|
|
|
exports.gte = gte
|
|
function gte (a, b, loose) {
|
|
return compare(a, b, loose) >= 0
|
|
}
|
|
|
|
exports.lte = lte
|
|
function lte (a, b, loose) {
|
|
return compare(a, b, loose) <= 0
|
|
}
|
|
|
|
exports.cmp = cmp
|
|
function cmp (a, op, b, loose) {
|
|
switch (op) {
|
|
case '===':
|
|
if (typeof a === 'object')
|
|
a = a.version
|
|
if (typeof b === 'object')
|
|
b = b.version
|
|
return a === b
|
|
|
|
case '!==':
|
|
if (typeof a === 'object')
|
|
a = a.version
|
|
if (typeof b === 'object')
|
|
b = b.version
|
|
return a !== b
|
|
|
|
case '':
|
|
case '=':
|
|
case '==':
|
|
return eq(a, b, loose)
|
|
|
|
case '!=':
|
|
return neq(a, b, loose)
|
|
|
|
case '>':
|
|
return gt(a, b, loose)
|
|
|
|
case '>=':
|
|
return gte(a, b, loose)
|
|
|
|
case '<':
|
|
return lt(a, b, loose)
|
|
|
|
case '<=':
|
|
return lte(a, b, loose)
|
|
|
|
default:
|
|
throw new TypeError('Invalid operator: ' + op)
|
|
}
|
|
}
|
|
|
|
exports.Comparator = Comparator
|
|
function Comparator (comp, options) {
|
|
if (!options || typeof options !== 'object') {
|
|
options = {
|
|
loose: !!options,
|
|
includePrerelease: false
|
|
}
|
|
}
|
|
|
|
if (comp instanceof Comparator) {
|
|
if (comp.loose === !!options.loose) {
|
|
return comp
|
|
} else {
|
|
comp = comp.value
|
|
}
|
|
}
|
|
|
|
if (!(this instanceof Comparator)) {
|
|
return new Comparator(comp, options)
|
|
}
|
|
|
|
debug('comparator', comp, options)
|
|
this.options = options
|
|
this.loose = !!options.loose
|
|
this.parse(comp)
|
|
|
|
if (this.semver === ANY) {
|
|
this.value = ''
|
|
} else {
|
|
this.value = this.operator + this.semver.version
|
|
}
|
|
|
|
debug('comp', this)
|
|
}
|
|
|
|
var ANY = {}
|
|
Comparator.prototype.parse = function (comp) {
|
|
var r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]
|
|
var m = comp.match(r)
|
|
|
|
if (!m) {
|
|
throw new TypeError('Invalid comparator: ' + comp)
|
|
}
|
|
|
|
this.operator = m[1] !== undefined ? m[1] : ''
|
|
if (this.operator === '=') {
|
|
this.operator = ''
|
|
}
|
|
|
|
// if it literally is just '>' or '' then allow anything.
|
|
if (!m[2]) {
|
|
this.semver = ANY
|
|
} else {
|
|
this.semver = new SemVer(m[2], this.options.loose)
|
|
}
|
|
}
|
|
|
|
Comparator.prototype.toString = function () {
|
|
return this.value
|
|
}
|
|
|
|
Comparator.prototype.test = function (version) {
|
|
debug('Comparator.test', version, this.options.loose)
|
|
|
|
if (this.semver === ANY || version === ANY) {
|
|
return true
|
|
}
|
|
|
|
if (typeof version === 'string') {
|
|
try {
|
|
version = new SemVer(version, this.options)
|
|
} catch (er) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return cmp(version, this.operator, this.semver, this.options)
|
|
}
|
|
|
|
Comparator.prototype.intersects = function (comp, options) {
|
|
if (!(comp instanceof Comparator)) {
|
|
throw new TypeError('a Comparator is required')
|
|
}
|
|
|
|
if (!options || typeof options !== 'object') {
|
|
options = {
|
|
loose: !!options,
|
|
includePrerelease: false
|
|
}
|
|
}
|
|
|
|
var rangeTmp
|
|
|
|
if (this.operator === '') {
|
|
if (this.value === '') {
|
|
return true
|
|
}
|
|
rangeTmp = new Range(comp.value, options)
|
|
return satisfies(this.value, rangeTmp, options)
|
|
} else if (comp.operator === '') {
|
|
if (comp.value === '') {
|
|
return true
|
|
}
|
|
rangeTmp = new Range(this.value, options)
|
|
return satisfies(comp.semver, rangeTmp, options)
|
|
}
|
|
|
|
var sameDirectionIncreasing =
|
|
(this.operator === '>=' || this.operator === '>') &&
|
|
(comp.operator === '>=' || comp.operator === '>')
|
|
var sameDirectionDecreasing =
|
|
(this.operator === '<=' || this.operator === '<') &&
|
|
(comp.operator === '<=' || comp.operator === '<')
|
|
var sameSemVer = this.semver.version === comp.semver.version
|
|
var differentDirectionsInclusive =
|
|
(this.operator === '>=' || this.operator === '<=') &&
|
|
(comp.operator === '>=' || comp.operator === '<=')
|
|
var oppositeDirectionsLessThan =
|
|
cmp(this.semver, '<', comp.semver, options) &&
|
|
((this.operator === '>=' || this.operator === '>') &&
|
|
(comp.operator === '<=' || comp.operator === '<'))
|
|
var oppositeDirectionsGreaterThan =
|
|
cmp(this.semver, '>', comp.semver, options) &&
|
|
((this.operator === '<=' || this.operator === '<') &&
|
|
(comp.operator === '>=' || comp.operator === '>'))
|
|
|
|
return sameDirectionIncreasing || sameDirectionDecreasing ||
|
|
(sameSemVer && differentDirectionsInclusive) ||
|
|
oppositeDirectionsLessThan || oppositeDirectionsGreaterThan
|
|
}
|
|
|
|
exports.Range = Range
|
|
function Range (range, options) {
|
|
if (!options || typeof options !== 'object') {
|
|
options = {
|
|
loose: !!options,
|
|
includePrerelease: false
|
|
}
|
|
}
|
|
|
|
if (range instanceof Range) {
|
|
if (range.loose === !!options.loose &&
|
|
range.includePrerelease === !!options.includePrerelease) {
|
|
return range
|
|
} else {
|
|
return new Range(range.raw, options)
|
|
}
|
|
}
|
|
|
|
if (range instanceof Comparator) {
|
|
return new Range(range.value, options)
|
|
}
|
|
|
|
if (!(this instanceof Range)) {
|
|
return new Range(range, options)
|
|
}
|
|
|
|
this.options = options
|
|
this.loose = !!options.loose
|
|
this.includePrerelease = !!options.includePrerelease
|
|
|
|
// First, split based on boolean or ||
|
|
this.raw = range
|
|
this.set = range.split(/\s*\|\|\s*/).map(function (range) {
|
|
return this.parseRange(range.trim())
|
|
}, this).filter(function (c) {
|
|
// throw out any that are not relevant for whatever reason
|
|
return c.length
|
|
})
|
|
|
|
if (!this.set.length) {
|
|
throw new TypeError('Invalid SemVer Range: ' + range)
|
|
}
|
|
|
|
this.format()
|
|
}
|
|
|
|
Range.prototype.format = function () {
|
|
this.range = this.set.map(function (comps) {
|
|
return comps.join(' ').trim()
|
|
}).join('||').trim()
|
|
return this.range
|
|
}
|
|
|
|
Range.prototype.toString = function () {
|
|
return this.range
|
|
}
|
|
|
|
Range.prototype.parseRange = function (range) {
|
|
var loose = this.options.loose
|
|
range = range.trim()
|
|
// `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
|
|
var hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]
|
|
range = range.replace(hr, hyphenReplace)
|
|
debug('hyphen replace', range)
|
|
// `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
|
|
range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace)
|
|
debug('comparator trim', range, re[t.COMPARATORTRIM])
|
|
|
|
// `~ 1.2.3` => `~1.2.3`
|
|
range = range.replace(re[t.TILDETRIM], tildeTrimReplace)
|
|
|
|
// `^ 1.2.3` => `^1.2.3`
|
|
range = range.replace(re[t.CARETTRIM], caretTrimReplace)
|
|
|
|
// normalize spaces
|
|
range = range.split(/\s+/).join(' ')
|
|
|
|
// At this point, the range is completely trimmed and
|
|
// ready to be split into comparators.
|
|
|
|
var compRe = loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]
|
|
var set = range.split(' ').map(function (comp) {
|
|
return parseComparator(comp, this.options)
|
|
}, this).join(' ').split(/\s+/)
|
|
if (this.options.loose) {
|
|
// in loose mode, throw out any that are not valid comparators
|
|
set = set.filter(function (comp) {
|
|
return !!comp.match(compRe)
|
|
})
|
|
}
|
|
set = set.map(function (comp) {
|
|
return new Comparator(comp, this.options)
|
|
}, this)
|
|
|
|
return set
|
|
}
|
|
|
|
Range.prototype.intersects = function (range, options) {
|
|
if (!(range instanceof Range)) {
|
|
throw new TypeError('a Range is required')
|
|
}
|
|
|
|
return this.set.some(function (thisComparators) {
|
|
return (
|
|
isSatisfiable(thisComparators, options) &&
|
|
range.set.some(function (rangeComparators) {
|
|
return (
|
|
isSatisfiable(rangeComparators, options) &&
|
|
thisComparators.every(function (thisComparator) {
|
|
return rangeComparators.every(function (rangeComparator) {
|
|
return thisComparator.intersects(rangeComparator, options)
|
|
})
|
|
})
|
|
)
|
|
})
|
|
)
|
|
})
|
|
}
|
|
|
|
// take a set of comparators and determine whether there
|
|
// exists a version which can satisfy it
|
|
function isSatisfiable (comparators, options) {
|
|
var result = true
|
|
var remainingComparators = comparators.slice()
|
|
var testComparator = remainingComparators.pop()
|
|
|
|
while (result && remainingComparators.length) {
|
|
result = remainingComparators.every(function (otherComparator) {
|
|
return testComparator.intersects(otherComparator, options)
|
|
})
|
|
|
|
testComparator = remainingComparators.pop()
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// Mostly just for testing and legacy API reasons
|
|
exports.toComparators = toComparators
|
|
function toComparators (range, options) {
|
|
return new Range(range, options).set.map(function (comp) {
|
|
return comp.map(function (c) {
|
|
return c.value
|
|
}).join(' ').trim().split(' ')
|
|
})
|
|
}
|
|
|
|
// comprised of xranges, tildes, stars, and gtlt's at this point.
|
|
// already replaced the hyphen ranges
|
|
// turn into a set of JUST comparators.
|
|
function parseComparator (comp, options) {
|
|
debug('comp', comp, options)
|
|
comp = replaceCarets(comp, options)
|
|
debug('caret', comp)
|
|
comp = replaceTildes(comp, options)
|
|
debug('tildes', comp)
|
|
comp = replaceXRanges(comp, options)
|
|
debug('xrange', comp)
|
|
comp = replaceStars(comp, options)
|
|
debug('stars', comp)
|
|
return comp
|
|
}
|
|
|
|
function isX (id) {
|
|
return !id || id.toLowerCase() === 'x' || id === '*'
|
|
}
|
|
|
|
// ~, ~> --> * (any, kinda silly)
|
|
// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0
|
|
// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0
|
|
// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0
|
|
// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0
|
|
// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0
|
|
function replaceTildes (comp, options) {
|
|
return comp.trim().split(/\s+/).map(function (comp) {
|
|
return replaceTilde(comp, options)
|
|
}).join(' ')
|
|
}
|
|
|
|
function replaceTilde (comp, options) {
|
|
var r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]
|
|
return comp.replace(r, function (_, M, m, p, pr) {
|
|
debug('tilde', comp, _, M, m, p, pr)
|
|
var ret
|
|
|
|
if (isX(M)) {
|
|
ret = ''
|
|
} else if (isX(m)) {
|
|
ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'
|
|
} else if (isX(p)) {
|
|
// ~1.2 == >=1.2.0 <1.3.0
|
|
ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'
|
|
} else if (pr) {
|
|
debug('replaceTilde pr', pr)
|
|
ret = '>=' + M + '.' + m + '.' + p + '-' + pr +
|
|
' <' + M + '.' + (+m + 1) + '.0'
|
|
} else {
|
|
// ~1.2.3 == >=1.2.3 <1.3.0
|
|
ret = '>=' + M + '.' + m + '.' + p +
|
|
' <' + M + '.' + (+m + 1) + '.0'
|
|
}
|
|
|
|
debug('tilde return', ret)
|
|
return ret
|
|
})
|
|
}
|
|
|
|
// ^ --> * (any, kinda silly)
|
|
// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0
|
|
// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0
|
|
// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0
|
|
// ^1.2.3 --> >=1.2.3 <2.0.0
|
|
// ^1.2.0 --> >=1.2.0 <2.0.0
|
|
function replaceCarets (comp, options) {
|
|
return comp.trim().split(/\s+/).map(function (comp) {
|
|
return replaceCaret(comp, options)
|
|
}).join(' ')
|
|
}
|
|
|
|
function replaceCaret (comp, options) {
|
|
debug('caret', comp, options)
|
|
var r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]
|
|
return comp.replace(r, function (_, M, m, p, pr) {
|
|
debug('caret', comp, _, M, m, p, pr)
|
|
var ret
|
|
|
|
if (isX(M)) {
|
|
ret = ''
|
|
} else if (isX(m)) {
|
|
ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'
|
|
} else if (isX(p)) {
|
|
if (M === '0') {
|
|
ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'
|
|
} else {
|
|
ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0'
|
|
}
|
|
} else if (pr) {
|
|
debug('replaceCaret pr', pr)
|
|
if (M === '0') {
|
|
if (m === '0') {
|
|
ret = '>=' + M + '.' + m + '.' + p + '-' + pr +
|
|
' <' + M + '.' + m + '.' + (+p + 1)
|
|
} else {
|
|
ret = '>=' + M + '.' + m + '.' + p + '-' + pr +
|
|
' <' + M + '.' + (+m + 1) + '.0'
|
|
}
|
|
} else {
|
|
ret = '>=' + M + '.' + m + '.' + p + '-' + pr +
|
|
' <' + (+M + 1) + '.0.0'
|
|
}
|
|
} else {
|
|
debug('no pr')
|
|
if (M === '0') {
|
|
if (m === '0') {
|
|
ret = '>=' + M + '.' + m + '.' + p +
|
|
' <' + M + '.' + m + '.' + (+p + 1)
|
|
} else {
|
|
ret = '>=' + M + '.' + m + '.' + p +
|
|
' <' + M + '.' + (+m + 1) + '.0'
|
|
}
|
|
} else {
|
|
ret = '>=' + M + '.' + m + '.' + p +
|
|
' <' + (+M + 1) + '.0.0'
|
|
}
|
|
}
|
|
|
|
debug('caret return', ret)
|
|
return ret
|
|
})
|
|
}
|
|
|
|
function replaceXRanges (comp, options) {
|
|
debug('replaceXRanges', comp, options)
|
|
return comp.split(/\s+/).map(function (comp) {
|
|
return replaceXRange(comp, options)
|
|
}).join(' ')
|
|
}
|
|
|
|
function replaceXRange (comp, options) {
|
|
comp = comp.trim()
|
|
var r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]
|
|
return comp.replace(r, function (ret, gtlt, M, m, p, pr) {
|
|
debug('xRange', comp, ret, gtlt, M, m, p, pr)
|
|
var xM = isX(M)
|
|
var xm = xM || isX(m)
|
|
var xp = xm || isX(p)
|
|
var anyX = xp
|
|
|
|
if (gtlt === '=' && anyX) {
|
|
gtlt = ''
|
|
}
|
|
|
|
// if we're including prereleases in the match, then we need
|
|
// to fix this to -0, the lowest possible prerelease value
|
|
pr = options.includePrerelease ? '-0' : ''
|
|
|
|
if (xM) {
|
|
if (gtlt === '>' || gtlt === '<') {
|
|
// nothing is allowed
|
|
ret = '<0.0.0-0'
|
|
} else {
|
|
// nothing is forbidden
|
|
ret = '*'
|
|
}
|
|
} else if (gtlt && anyX) {
|
|
// we know patch is an x, because we have any x at all.
|
|
// replace X with 0
|
|
if (xm) {
|
|
m = 0
|
|
}
|
|
p = 0
|
|
|
|
if (gtlt === '>') {
|
|
// >1 => >=2.0.0
|
|
// >1.2 => >=1.3.0
|
|
// >1.2.3 => >= 1.2.4
|
|
gtlt = '>='
|
|
if (xm) {
|
|
M = +M + 1
|
|
m = 0
|
|
p = 0
|
|
} else {
|
|
m = +m + 1
|
|
p = 0
|
|
}
|
|
} else if (gtlt === '<=') {
|
|
// <=0.7.x is actually <0.8.0, since any 0.7.x should
|
|
// pass. Similarly, <=7.x is actually <8.0.0, etc.
|
|
gtlt = '<'
|
|
if (xm) {
|
|
M = +M + 1
|
|
} else {
|
|
m = +m + 1
|
|
}
|
|
}
|
|
|
|
ret = gtlt + M + '.' + m + '.' + p + pr
|
|
} else if (xm) {
|
|
ret = '>=' + M + '.0.0' + pr + ' <' + (+M + 1) + '.0.0' + pr
|
|
} else if (xp) {
|
|
ret = '>=' + M + '.' + m + '.0' + pr +
|
|
' <' + M + '.' + (+m + 1) + '.0' + pr
|
|
}
|
|
|
|
debug('xRange return', ret)
|
|
|
|
return ret
|
|
})
|
|
}
|
|
|
|
// Because * is AND-ed with everything else in the comparator,
|
|
// and '' means "any version", just remove the *s entirely.
|
|
function replaceStars (comp, options) {
|
|
debug('replaceStars', comp, options)
|
|
// Looseness is ignored here. star is always as loose as it gets!
|
|
return comp.trim().replace(re[t.STAR], '')
|
|
}
|
|
|
|
// This function is passed to string.replace(re[t.HYPHENRANGE])
|
|
// M, m, patch, prerelease, build
|
|
// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5
|
|
// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do
|
|
// 1.2 - 3.4 => >=1.2.0 <3.5.0
|
|
function hyphenReplace ($0,
|
|
from, fM, fm, fp, fpr, fb,
|
|
to, tM, tm, tp, tpr, tb) {
|
|
if (isX(fM)) {
|
|
from = ''
|
|
} else if (isX(fm)) {
|
|
from = '>=' + fM + '.0.0'
|
|
} else if (isX(fp)) {
|
|
from = '>=' + fM + '.' + fm + '.0'
|
|
} else {
|
|
from = '>=' + from
|
|
}
|
|
|
|
if (isX(tM)) {
|
|
to = ''
|
|
} else if (isX(tm)) {
|
|
to = '<' + (+tM + 1) + '.0.0'
|
|
} else if (isX(tp)) {
|
|
to = '<' + tM + '.' + (+tm + 1) + '.0'
|
|
} else if (tpr) {
|
|
to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr
|
|
} else {
|
|
to = '<=' + to
|
|
}
|
|
|
|
return (from + ' ' + to).trim()
|
|
}
|
|
|
|
// if ANY of the sets match ALL of its comparators, then pass
|
|
Range.prototype.test = function (version) {
|
|
if (!version) {
|
|
return false
|
|
}
|
|
|
|
if (typeof version === 'string') {
|
|
try {
|
|
version = new SemVer(version, this.options)
|
|
} catch (er) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
for (var i = 0; i < this.set.length; i++) {
|
|
if (testSet(this.set[i], version, this.options)) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
function testSet (set, version, options) {
|
|
for (var i = 0; i < set.length; i++) {
|
|
if (!set[i].test(version)) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
if (version.prerelease.length && !options.includePrerelease) {
|
|
// Find the set of versions that are allowed to have prereleases
|
|
// For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0
|
|
// That should allow `1.2.3-pr.2` to pass.
|
|
// However, `1.2.4-alpha.notready` should NOT be allowed,
|
|
// even though it's within the range set by the comparators.
|
|
for (i = 0; i < set.length; i++) {
|
|
debug(set[i].semver)
|
|
if (set[i].semver === ANY) {
|
|
continue
|
|
}
|
|
|
|
if (set[i].semver.prerelease.length > 0) {
|
|
var allowed = set[i].semver
|
|
if (allowed.major === version.major &&
|
|
allowed.minor === version.minor &&
|
|
allowed.patch === version.patch) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
// Version has a -pre, but it's not one of the ones we like.
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
exports.satisfies = satisfies
|
|
function satisfies (version, range, options) {
|
|
try {
|
|
range = new Range(range, options)
|
|
} catch (er) {
|
|
return false
|
|
}
|
|
return range.test(version)
|
|
}
|
|
|
|
exports.maxSatisfying = maxSatisfying
|
|
function maxSatisfying (versions, range, options) {
|
|
var max = null
|
|
var maxSV = null
|
|
try {
|
|
var rangeObj = new Range(range, options)
|
|
} catch (er) {
|
|
return null
|
|
}
|
|
versions.forEach(function (v) {
|
|
if (rangeObj.test(v)) {
|
|
// satisfies(v, range, options)
|
|
if (!max || maxSV.compare(v) === -1) {
|
|
// compare(max, v, true)
|
|
max = v
|
|
maxSV = new SemVer(max, options)
|
|
}
|
|
}
|
|
})
|
|
return max
|
|
}
|
|
|
|
exports.minSatisfying = minSatisfying
|
|
function minSatisfying (versions, range, options) {
|
|
var min = null
|
|
var minSV = null
|
|
try {
|
|
var rangeObj = new Range(range, options)
|
|
} catch (er) {
|
|
return null
|
|
}
|
|
versions.forEach(function (v) {
|
|
if (rangeObj.test(v)) {
|
|
// satisfies(v, range, options)
|
|
if (!min || minSV.compare(v) === 1) {
|
|
// compare(min, v, true)
|
|
min = v
|
|
minSV = new SemVer(min, options)
|
|
}
|
|
}
|
|
})
|
|
return min
|
|
}
|
|
|
|
exports.minVersion = minVersion
|
|
function minVersion (range, loose) {
|
|
range = new Range(range, loose)
|
|
|
|
var minver = new SemVer('0.0.0')
|
|
if (range.test(minver)) {
|
|
return minver
|
|
}
|
|
|
|
minver = new SemVer('0.0.0-0')
|
|
if (range.test(minver)) {
|
|
return minver
|
|
}
|
|
|
|
minver = null
|
|
for (var i = 0; i < range.set.length; ++i) {
|
|
var comparators = range.set[i]
|
|
|
|
comparators.forEach(function (comparator) {
|
|
// Clone to avoid manipulating the comparator's semver object.
|
|
var compver = new SemVer(comparator.semver.version)
|
|
switch (comparator.operator) {
|
|
case '>':
|
|
if (compver.prerelease.length === 0) {
|
|
compver.patch++
|
|
} else {
|
|
compver.prerelease.push(0)
|
|
}
|
|
compver.raw = compver.format()
|
|
/* fallthrough */
|
|
case '':
|
|
case '>=':
|
|
if (!minver || gt(minver, compver)) {
|
|
minver = compver
|
|
}
|
|
break
|
|
case '<':
|
|
case '<=':
|
|
/* Ignore maximum versions */
|
|
break
|
|
/* istanbul ignore next */
|
|
default:
|
|
throw new Error('Unexpected operation: ' + comparator.operator)
|
|
}
|
|
})
|
|
}
|
|
|
|
if (minver && range.test(minver)) {
|
|
return minver
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
exports.validRange = validRange
|
|
function validRange (range, options) {
|
|
try {
|
|
// Return '*' instead of '' so that truthiness works.
|
|
// This will throw if it's invalid anyway
|
|
return new Range(range, options).range || '*'
|
|
} catch (er) {
|
|
return null
|
|
}
|
|
}
|
|
|
|
// Determine if version is less than all the versions possible in the range
|
|
exports.ltr = ltr
|
|
function ltr (version, range, options) {
|
|
return outside(version, range, '<', options)
|
|
}
|
|
|
|
// Determine if version is greater than all the versions possible in the range.
|
|
exports.gtr = gtr
|
|
function gtr (version, range, options) {
|
|
return outside(version, range, '>', options)
|
|
}
|
|
|
|
exports.outside = outside
|
|
function outside (version, range, hilo, options) {
|
|
version = new SemVer(version, options)
|
|
range = new Range(range, options)
|
|
|
|
var gtfn, ltefn, ltfn, comp, ecomp
|
|
switch (hilo) {
|
|
case '>':
|
|
gtfn = gt
|
|
ltefn = lte
|
|
ltfn = lt
|
|
comp = '>'
|
|
ecomp = '>='
|
|
break
|
|
case '<':
|
|
gtfn = lt
|
|
ltefn = gte
|
|
ltfn = gt
|
|
comp = '<'
|
|
ecomp = '<='
|
|
break
|
|
default:
|
|
throw new TypeError('Must provide a hilo val of "<" or ">"')
|
|
}
|
|
|
|
// If it satisifes the range it is not outside
|
|
if (satisfies(version, range, options)) {
|
|
return false
|
|
}
|
|
|
|
// From now on, variable terms are as if we're in "gtr" mode.
|
|
// but note that everything is flipped for the "ltr" function.
|
|
|
|
for (var i = 0; i < range.set.length; ++i) {
|
|
var comparators = range.set[i]
|
|
|
|
var high = null
|
|
var low = null
|
|
|
|
comparators.forEach(function (comparator) {
|
|
if (comparator.semver === ANY) {
|
|
comparator = new Comparator('>=0.0.0')
|
|
}
|
|
high = high || comparator
|
|
low = low || comparator
|
|
if (gtfn(comparator.semver, high.semver, options)) {
|
|
high = comparator
|
|
} else if (ltfn(comparator.semver, low.semver, options)) {
|
|
low = comparator
|
|
}
|
|
})
|
|
|
|
// If the edge version comparator has a operator then our version
|
|
// isn't outside it
|
|
if (high.operator === comp || high.operator === ecomp) {
|
|
return false
|
|
}
|
|
|
|
// If the lowest version comparator has an operator and our version
|
|
// is less than it then it isn't higher than the range
|
|
if ((!low.operator || low.operator === comp) &&
|
|
ltefn(version, low.semver)) {
|
|
return false
|
|
} else if (low.operator === ecomp && ltfn(version, low.semver)) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
exports.prerelease = prerelease
|
|
function prerelease (version, options) {
|
|
var parsed = parse(version, options)
|
|
return (parsed && parsed.prerelease.length) ? parsed.prerelease : null
|
|
}
|
|
|
|
exports.intersects = intersects
|
|
function intersects (r1, r2, options) {
|
|
r1 = new Range(r1, options)
|
|
r2 = new Range(r2, options)
|
|
return r1.intersects(r2)
|
|
}
|
|
|
|
exports.coerce = coerce
|
|
function coerce (version, options) {
|
|
if (version instanceof SemVer) {
|
|
return version
|
|
}
|
|
|
|
if (typeof version === 'number') {
|
|
version = String(version)
|
|
}
|
|
|
|
if (typeof version !== 'string') {
|
|
return null
|
|
}
|
|
|
|
options = options || {}
|
|
|
|
var match = null
|
|
if (!options.rtl) {
|
|
match = version.match(re[t.COERCE])
|
|
} else {
|
|
// Find the right-most coercible string that does not share
|
|
// a terminus with a more left-ward coercible string.
|
|
// Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4'
|
|
//
|
|
// Walk through the string checking with a /g regexp
|
|
// Manually set the index so as to pick up overlapping matches.
|
|
// Stop when we get a match that ends at the string end, since no
|
|
// coercible string can be more right-ward without the same terminus.
|
|
var next
|
|
while ((next = re[t.COERCERTL].exec(version)) &&
|
|
(!match || match.index + match[0].length !== version.length)
|
|
) {
|
|
if (!match ||
|
|
next.index + next[0].length !== match.index + match[0].length) {
|
|
match = next
|
|
}
|
|
re[t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length
|
|
}
|
|
// leave it in a clean state
|
|
re[t.COERCERTL].lastIndex = -1
|
|
}
|
|
|
|
if (match === null) {
|
|
return null
|
|
}
|
|
|
|
return parse(match[2] +
|
|
'.' + (match[3] || '0') +
|
|
'.' + (match[4] || '0'), options)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 2 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const neovim_1 = __webpack_require__(4);
|
|
const log4js_1 = tslib_1.__importDefault(__webpack_require__(64));
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const plugin_1 = tslib_1.__importDefault(__webpack_require__(231));
|
|
const semver_1 = tslib_1.__importDefault(__webpack_require__(1));
|
|
__webpack_require__(309);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const logger = __webpack_require__(186)('attach');
|
|
const isTest = "none" == 'test';
|
|
exports.default = (opts, requestApi = true) => {
|
|
const nvim = neovim_1.attach(opts, log4js_1.default.getLogger('node-client'), requestApi);
|
|
// Overwriding the URI.file function in case of cygwin.
|
|
nvim.eval('has("win32unix")?get(g:,"coc_cygqwin_path_prefixes", v:null):v:null').then(prefixes => {
|
|
if (!prefixes)
|
|
return;
|
|
const old_uri = vscode_uri_1.URI.file;
|
|
vscode_uri_1.URI.file = (path) => {
|
|
path = path.replace(/\\/g, '/');
|
|
Object.keys(prefixes).forEach(k => path = path.replace(new RegExp('^' + k, 'gi'), prefixes[k]));
|
|
return old_uri(path);
|
|
};
|
|
}).logError();
|
|
const plugin = new plugin_1.default(nvim);
|
|
let clientReady = false;
|
|
let initialized = false;
|
|
nvim.on('notification', async (method, args) => {
|
|
switch (method) {
|
|
case 'VimEnter': {
|
|
if (!initialized && clientReady) {
|
|
initialized = true;
|
|
await plugin.init();
|
|
}
|
|
break;
|
|
}
|
|
case 'TaskExit':
|
|
case 'TaskStderr':
|
|
case 'TaskStdout':
|
|
case 'GlobalChange':
|
|
case 'InputChar':
|
|
case 'OptionSet':
|
|
await events_1.default.fire(method, args);
|
|
break;
|
|
case 'CocAutocmd':
|
|
await events_1.default.fire(args[0], args.slice(1));
|
|
break;
|
|
default:
|
|
const m = method[0].toLowerCase() + method.slice(1);
|
|
if (typeof plugin[m] == 'function') {
|
|
try {
|
|
await Promise.resolve(plugin[m].apply(plugin, args));
|
|
}
|
|
catch (e) {
|
|
// tslint:disable-next-line:no-console
|
|
console.error(`error on notification '${method}': ${e}`);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
nvim.on('request', async (method, args, resp) => {
|
|
try {
|
|
if (method == 'CocAutocmd') {
|
|
await events_1.default.fire(args[0], args.slice(1));
|
|
resp.send();
|
|
return;
|
|
}
|
|
let m = method[0].toLowerCase() + method.slice(1);
|
|
if (typeof plugin[m] !== 'function') {
|
|
return resp.send(`Method ${m} not found`, true);
|
|
}
|
|
let res = await Promise.resolve(plugin[m].apply(plugin, args));
|
|
resp.send(res);
|
|
}
|
|
catch (e) {
|
|
logger.error(`Error on "${method}": ` + e.stack);
|
|
resp.send(e.message, true);
|
|
}
|
|
});
|
|
nvim.channelId.then(async (channelId) => {
|
|
clientReady = true;
|
|
if (isTest)
|
|
nvim.command(`let g:coc_node_channel_id = ${channelId}`, true);
|
|
let json = __webpack_require__(410);
|
|
let { major, minor, patch } = semver_1.default.parse(json.version);
|
|
nvim.setClientInfo('coc', { major, minor, patch }, 'remote', {}, {});
|
|
let entered = await nvim.getVvar('vim_did_enter');
|
|
if (entered && !initialized) {
|
|
initialized = true;
|
|
await plugin.init();
|
|
}
|
|
}).catch(e => {
|
|
console.error(`Channel create error: ${e.message}`); // tslint:disable-line
|
|
});
|
|
return plugin;
|
|
};
|
|
//# sourceMappingURL=attach.js.map
|
|
|
|
/***/ }),
|
|
/* 3 */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__extends", function() { return __extends; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__assign", function() { return __assign; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__rest", function() { return __rest; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__decorate", function() { return __decorate; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__param", function() { return __param; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__metadata", function() { return __metadata; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__awaiter", function() { return __awaiter; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__generator", function() { return __generator; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__exportStar", function() { return __exportStar; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__values", function() { return __values; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__read", function() { return __read; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__spread", function() { return __spread; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__spreadArrays", function() { return __spreadArrays; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__await", function() { return __await; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__asyncGenerator", function() { return __asyncGenerator; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__asyncDelegator", function() { return __asyncDelegator; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__asyncValues", function() { return __asyncValues; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__makeTemplateObject", function() { return __makeTemplateObject; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__importStar", function() { return __importStar; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__importDefault", function() { return __importDefault; });
|
|
/*! *****************************************************************************
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
this file except in compliance with the License. You may obtain a copy of the
|
|
License at http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
|
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
|
MERCHANTABLITY OR NON-INFRINGEMENT.
|
|
|
|
See the Apache Version 2.0 License for specific language governing permissions
|
|
and limitations under the License.
|
|
***************************************************************************** */
|
|
/* global Reflect, Promise */
|
|
|
|
var extendStatics = function(d, b) {
|
|
extendStatics = Object.setPrototypeOf ||
|
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
|
return extendStatics(d, b);
|
|
};
|
|
|
|
function __extends(d, b) {
|
|
extendStatics(d, b);
|
|
function __() { this.constructor = d; }
|
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
}
|
|
|
|
var __assign = function() {
|
|
__assign = Object.assign || function __assign(t) {
|
|
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
s = arguments[i];
|
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
}
|
|
return t;
|
|
}
|
|
return __assign.apply(this, arguments);
|
|
}
|
|
|
|
function __rest(s, e) {
|
|
var t = {};
|
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
t[p] = s[p];
|
|
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
t[p[i]] = s[p[i]];
|
|
}
|
|
return t;
|
|
}
|
|
|
|
function __decorate(decorators, target, key, desc) {
|
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
}
|
|
|
|
function __param(paramIndex, decorator) {
|
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
}
|
|
|
|
function __metadata(metadataKey, metadataValue) {
|
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
|
|
}
|
|
|
|
function __awaiter(thisArg, _arguments, P, generator) {
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
}
|
|
|
|
function __generator(thisArg, body) {
|
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
function step(op) {
|
|
if (f) throw new TypeError("Generator is already executing.");
|
|
while (_) try {
|
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
switch (op[0]) {
|
|
case 0: case 1: t = op; break;
|
|
case 4: _.label++; return { value: op[1], done: false };
|
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
default:
|
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
if (t[2]) _.ops.pop();
|
|
_.trys.pop(); continue;
|
|
}
|
|
op = body.call(thisArg, _);
|
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
}
|
|
}
|
|
|
|
function __exportStar(m, exports) {
|
|
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|
}
|
|
|
|
function __values(o) {
|
|
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
|
|
if (m) return m.call(o);
|
|
return {
|
|
next: function () {
|
|
if (o && i >= o.length) o = void 0;
|
|
return { value: o && o[i++], done: !o };
|
|
}
|
|
};
|
|
}
|
|
|
|
function __read(o, n) {
|
|
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
if (!m) return o;
|
|
var i = m.call(o), r, ar = [], e;
|
|
try {
|
|
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
}
|
|
catch (error) { e = { error: error }; }
|
|
finally {
|
|
try {
|
|
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
}
|
|
finally { if (e) throw e.error; }
|
|
}
|
|
return ar;
|
|
}
|
|
|
|
function __spread() {
|
|
for (var ar = [], i = 0; i < arguments.length; i++)
|
|
ar = ar.concat(__read(arguments[i]));
|
|
return ar;
|
|
}
|
|
|
|
function __spreadArrays() {
|
|
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
|
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
|
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
|
r[k] = a[j];
|
|
return r;
|
|
};
|
|
|
|
function __await(v) {
|
|
return this instanceof __await ? (this.v = v, this) : new __await(v);
|
|
}
|
|
|
|
function __asyncGenerator(thisArg, _arguments, generator) {
|
|
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
|
|
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
function fulfill(value) { resume("next", value); }
|
|
function reject(value) { resume("throw", value); }
|
|
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
}
|
|
|
|
function __asyncDelegator(o) {
|
|
var i, p;
|
|
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
|
|
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
|
|
}
|
|
|
|
function __asyncValues(o) {
|
|
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
var m = o[Symbol.asyncIterator], i;
|
|
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
}
|
|
|
|
function __makeTemplateObject(cooked, raw) {
|
|
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
|
|
return cooked;
|
|
};
|
|
|
|
function __importStar(mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
result.default = mod;
|
|
return result;
|
|
}
|
|
|
|
function __importDefault(mod) {
|
|
return (mod && mod.__esModule) ? mod : { default: mod };
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 4 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
var attach_1 = __webpack_require__(5);
|
|
exports.attach = attach_1.attach;
|
|
var index_1 = __webpack_require__(63);
|
|
exports.Neovim = index_1.Neovim;
|
|
exports.NeovimClient = index_1.NeovimClient;
|
|
exports.Buffer = index_1.Buffer;
|
|
exports.Tabpage = index_1.Tabpage;
|
|
exports.Window = index_1.Window;
|
|
|
|
|
|
/***/ }),
|
|
/* 5 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const net_1 = __webpack_require__(6);
|
|
const client_1 = __webpack_require__(7);
|
|
function attach({ reader: _reader, writer: _writer, proc, socket, }, _logger = null, requestApi = true) {
|
|
let writer;
|
|
let reader;
|
|
let neovim;
|
|
if (socket) {
|
|
const client = net_1.createConnection(socket);
|
|
writer = client;
|
|
reader = client;
|
|
client.once('close', () => {
|
|
neovim.detach();
|
|
});
|
|
}
|
|
else if (_reader && _writer) {
|
|
writer = _writer;
|
|
reader = _reader;
|
|
}
|
|
else if (proc) {
|
|
writer = proc.stdin;
|
|
reader = proc.stdout;
|
|
proc.once('disconnect', () => {
|
|
neovim.detach();
|
|
});
|
|
}
|
|
writer.on('error', err => {
|
|
if (err.code == 'EPIPE') {
|
|
neovim.detach();
|
|
}
|
|
});
|
|
if (writer && reader) {
|
|
neovim = new client_1.NeovimClient();
|
|
neovim.attach({
|
|
writer,
|
|
reader,
|
|
}, requestApi);
|
|
return neovim;
|
|
}
|
|
throw new Error('Invalid arguments, could not attach');
|
|
}
|
|
exports.attach = attach;
|
|
|
|
|
|
/***/ }),
|
|
/* 6 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("net");
|
|
|
|
/***/ }),
|
|
/* 7 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
/**
|
|
* Handles attaching transport
|
|
*/
|
|
const nvim_1 = __webpack_require__(8);
|
|
const vim_1 = __webpack_require__(58);
|
|
const Neovim_1 = __webpack_require__(62);
|
|
const Buffer_1 = __webpack_require__(47);
|
|
const Window_1 = __webpack_require__(50);
|
|
const Tabpage_1 = __webpack_require__(52);
|
|
const logger_1 = __webpack_require__(54);
|
|
exports.DETACH_BUFFER = Symbol('detachBuffer');
|
|
exports.ATTACH_BUFFER = Symbol('attachBuffer');
|
|
const logger = logger_1.createLogger('client');
|
|
const isVim = process.env.VIM_NODE_RPC == '1';
|
|
class AsyncResponse {
|
|
constructor(requestId, cb) {
|
|
this.requestId = requestId;
|
|
this.cb = cb;
|
|
this.finished = false;
|
|
}
|
|
finish(err, res) {
|
|
if (this.finished)
|
|
return;
|
|
this.finished = true;
|
|
if (err) {
|
|
this.cb(new Error(err));
|
|
return;
|
|
}
|
|
this.cb(null, res);
|
|
}
|
|
}
|
|
exports.AsyncResponse = AsyncResponse;
|
|
class NeovimClient extends Neovim_1.Neovim {
|
|
constructor() {
|
|
// Neovim has no `data` or `metadata`
|
|
super({});
|
|
this.requestId = 1;
|
|
this.responses = new Map();
|
|
this.attachedBuffers = new Map();
|
|
this.pauseLevel = 0;
|
|
Object.defineProperty(this, 'client', {
|
|
value: this
|
|
});
|
|
let transport = isVim ? new vim_1.VimTransport() : new nvim_1.NvimTransport();
|
|
this.setTransport(transport);
|
|
this.transportAttached = false;
|
|
this.handleRequest = this.handleRequest.bind(this);
|
|
this.handleNotification = this.handleNotification.bind(this);
|
|
}
|
|
createBuffer(id) {
|
|
return new Buffer_1.Buffer({
|
|
transport: this.transport,
|
|
data: id,
|
|
client: this
|
|
});
|
|
}
|
|
createWindow(id) {
|
|
return new Window_1.Window({
|
|
transport: this.transport,
|
|
data: id,
|
|
client: this
|
|
});
|
|
}
|
|
createTabpage(id) {
|
|
return new Tabpage_1.Tabpage({
|
|
transport: this.transport,
|
|
data: id,
|
|
client: this
|
|
});
|
|
}
|
|
/** Attaches msgpack to read/write streams * */
|
|
attach({ reader, writer, }, requestApi = true) {
|
|
this.transport.attach(writer, reader, this);
|
|
this.transportAttached = true;
|
|
this.setupTransport(requestApi);
|
|
}
|
|
/* called when attach process disconnected*/
|
|
detach() {
|
|
this.transport.detach();
|
|
this.transportAttached = false;
|
|
}
|
|
get isApiReady() {
|
|
return this.transportAttached && typeof this._channelId !== 'undefined';
|
|
}
|
|
get channelId() {
|
|
return this._isReady.then(() => {
|
|
return this._channelId;
|
|
});
|
|
}
|
|
isAttached(bufnr) {
|
|
return this.attachedBuffers.has(bufnr);
|
|
}
|
|
handleRequest(method, args, resp) {
|
|
this.emit('request', method, args, resp);
|
|
}
|
|
sendAsyncRequest(method, args) {
|
|
let id = this.requestId;
|
|
this.requestId = id + 1;
|
|
this.notify('nvim_call_function', ['coc#rpc#async_request', [id, method, args || []]]);
|
|
return new Promise((resolve, reject) => {
|
|
let response = new AsyncResponse(id, (err, res) => {
|
|
if (err)
|
|
return reject(err);
|
|
resolve(res);
|
|
});
|
|
this.responses.set(id, response);
|
|
});
|
|
}
|
|
emitNotification(method, args) {
|
|
if (method.endsWith('_event')) {
|
|
if (method.startsWith('nvim_buf_')) {
|
|
const shortName = method.replace(/nvim_buf_(.*)_event/, '$1');
|
|
const buffer = args[0];
|
|
const { id } = buffer;
|
|
if (!this.isAttached(id)) {
|
|
// this is a problem
|
|
return;
|
|
}
|
|
const bufferMap = this.attachedBuffers.get(id);
|
|
const cbs = bufferMap.get(shortName) || [];
|
|
cbs.forEach(cb => cb(...args));
|
|
// Handle `nvim_buf_detach_event`
|
|
// clean `attachedBuffers` since it will no longer be attached
|
|
if (shortName === 'detach') {
|
|
this.attachedBuffers.delete(id);
|
|
}
|
|
return;
|
|
}
|
|
// async_request_event from vim
|
|
if (method.startsWith('nvim_async_request')) {
|
|
const [id, method, arr] = args;
|
|
this.handleRequest(method, arr, {
|
|
send: (resp, isError) => {
|
|
this.notify('nvim_call_function', ['coc#rpc#async_response', [id, resp, isError]]);
|
|
}
|
|
});
|
|
}
|
|
// nvim_async_response_event
|
|
if (method.startsWith('nvim_async_response')) {
|
|
const [id, err, res] = args;
|
|
const response = this.responses.get(id);
|
|
if (!response) {
|
|
// tslint:disable-next-line: no-console
|
|
console.error(`Response not found for request ${id}`);
|
|
return;
|
|
}
|
|
this.responses.delete(id);
|
|
response.finish(err, res);
|
|
return;
|
|
}
|
|
// tslint:disable-next-line: no-console
|
|
// console.error(`Unhandled event: ${method}`)
|
|
}
|
|
else {
|
|
this.emit('notification', method, args);
|
|
}
|
|
}
|
|
handleNotification(method, args) {
|
|
this.emitNotification(method, args);
|
|
}
|
|
// Listen and setup handlers for transport
|
|
setupTransport(requestApi = true) {
|
|
if (!this.transportAttached) {
|
|
throw new Error('Not attached to input/output');
|
|
}
|
|
this.transport.on('request', this.handleRequest);
|
|
this.transport.on('notification', this.handleNotification);
|
|
this.transport.on('detach', () => {
|
|
this.emit('disconnect');
|
|
this.transport.removeAllListeners('request');
|
|
this.transport.removeAllListeners('notification');
|
|
this.transport.removeAllListeners('detach');
|
|
});
|
|
if (requestApi) {
|
|
this._isReady = this.generateApi();
|
|
}
|
|
else {
|
|
this._channelId = 0;
|
|
this._isReady = Promise.resolve(true);
|
|
}
|
|
}
|
|
requestApi() {
|
|
return new Promise((resolve, reject) => {
|
|
this.transport.request('nvim_get_api_info', [], (err, res) => {
|
|
if (err) {
|
|
reject(new Error(Array.isArray(err) ? err[1] : err.message || err.toString()));
|
|
}
|
|
else {
|
|
resolve(res);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
generateApi() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
let results;
|
|
try {
|
|
results = yield this.requestApi();
|
|
}
|
|
catch (err) {
|
|
// tslint:disable-next-line: no-console
|
|
console.error('Could not get vim api results');
|
|
logger.error(err);
|
|
}
|
|
if (results) {
|
|
try {
|
|
const [channelId, metadata] = results;
|
|
this.functions = metadata.functions.map(f => f.name);
|
|
this._channelId = channelId;
|
|
return true;
|
|
}
|
|
catch (err) {
|
|
logger.error(err.stack);
|
|
return null;
|
|
}
|
|
}
|
|
return null;
|
|
});
|
|
}
|
|
[exports.ATTACH_BUFFER](buffer) {
|
|
this.attachedBuffers.set(buffer.id, new Map());
|
|
}
|
|
[exports.DETACH_BUFFER](buffer) {
|
|
this.attachedBuffers.delete(buffer.id);
|
|
}
|
|
attachBufferEvent(buffer, eventName, cb) {
|
|
if (!this.isAttached(buffer.id))
|
|
return;
|
|
const bufferMap = this.attachedBuffers.get(buffer.id);
|
|
if (!bufferMap.get(eventName)) {
|
|
bufferMap.set(eventName, []);
|
|
}
|
|
const cbs = bufferMap.get(eventName);
|
|
if (cbs.indexOf(cb) !== -1)
|
|
return;
|
|
cbs.push(cb);
|
|
bufferMap.set(eventName, cbs);
|
|
this.attachedBuffers.set(buffer.id, bufferMap);
|
|
return;
|
|
}
|
|
/**
|
|
* Returns `true` if buffer should be detached
|
|
*/
|
|
detachBufferEvent(buffer, eventName, cb) {
|
|
const bufferMap = this.attachedBuffers.get(buffer.id);
|
|
if (!bufferMap)
|
|
return;
|
|
const handlers = (bufferMap.get(eventName) || []).filter(handler => handler !== cb);
|
|
// Remove eventName listener from bufferMap if no more handlers
|
|
if (!handlers.length) {
|
|
bufferMap.delete(eventName);
|
|
}
|
|
else {
|
|
bufferMap.set(eventName, handlers);
|
|
}
|
|
}
|
|
pauseNotification() {
|
|
this.pauseLevel = this.pauseLevel + 1;
|
|
this.transport.pauseNotification();
|
|
if (this.pauseTimer)
|
|
clearTimeout(this.pauseTimer);
|
|
this.pauseTimer = setTimeout(() => {
|
|
this.pauseLevel = 0;
|
|
// tslint:disable-next-line: no-floating-promises
|
|
this.transport.resumeNotification();
|
|
}, 50);
|
|
}
|
|
resumeNotification(cancel, notify) {
|
|
if (this.pauseLevel == 0)
|
|
return Promise.resolve();
|
|
this.pauseLevel = this.pauseLevel - 1;
|
|
if (cancel)
|
|
return Promise.resolve();
|
|
if (this.pauseLevel == 0) {
|
|
if (this.pauseTimer)
|
|
clearTimeout(this.pauseTimer);
|
|
if (!notify)
|
|
return this.transport.resumeNotification();
|
|
this.transport.resumeNotification(true);
|
|
}
|
|
return Promise.resolve();
|
|
}
|
|
hasFunction(name) {
|
|
if (!this.functions)
|
|
return true;
|
|
return this.functions.indexOf(name) !== -1;
|
|
}
|
|
}
|
|
exports.NeovimClient = NeovimClient;
|
|
|
|
|
|
/***/ }),
|
|
/* 8 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
result["default"] = mod;
|
|
return result;
|
|
};
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const msgpack = __importStar(__webpack_require__(9));
|
|
const buffered_1 = __importDefault(__webpack_require__(45));
|
|
const types_1 = __webpack_require__(46);
|
|
const base_1 = __importDefault(__webpack_require__(53));
|
|
class NvimTransport extends base_1.default {
|
|
constructor() {
|
|
super();
|
|
this.pending = new Map();
|
|
this.nextRequestId = 1;
|
|
this.attached = false;
|
|
const codec = this.setupCodec();
|
|
this.encodeStream = msgpack.createEncodeStream({ codec });
|
|
this.decodeStream = msgpack.createDecodeStream({ codec });
|
|
this.decodeStream.on('data', (msg) => {
|
|
this.parseMessage(msg);
|
|
});
|
|
this.decodeStream.on('end', () => {
|
|
this.detach();
|
|
this.emit('detach');
|
|
});
|
|
}
|
|
parseMessage(msg) {
|
|
const msgType = msg[0];
|
|
this.debugMessage(msg);
|
|
if (msgType === 0) {
|
|
// request
|
|
// - msg[1]: id
|
|
// - msg[2]: method name
|
|
// - msg[3]: arguments
|
|
this.emit('request', msg[2].toString(), msg[3], this.createResponse(msg[1]));
|
|
}
|
|
else if (msgType === 1) {
|
|
// response to a previous request:
|
|
// - msg[1]: the id
|
|
// - msg[2]: error(if any)
|
|
// - msg[3]: result(if not errored)
|
|
const id = msg[1];
|
|
const handler = this.pending.get(id);
|
|
if (handler) {
|
|
this.pending.delete(id);
|
|
let err = msg[2];
|
|
if (err && err.length != 2) {
|
|
err = [0, err instanceof Error ? err.message : err];
|
|
}
|
|
handler(err, msg[3]);
|
|
}
|
|
}
|
|
else if (msgType === 2) {
|
|
// notification/event
|
|
// - msg[1]: event name
|
|
// - msg[2]: arguments
|
|
this.emit('notification', msg[1].toString(), msg[2]);
|
|
}
|
|
else {
|
|
// tslint:disable-next-line: no-console
|
|
console.error(`Invalid message type ${msgType}`);
|
|
}
|
|
}
|
|
setupCodec() {
|
|
const codec = msgpack.createCodec();
|
|
types_1.Metadata.forEach(({ constructor }, id) => {
|
|
codec.addExtPacker(id, constructor, (obj) => msgpack.encode(obj.data));
|
|
codec.addExtUnpacker(id, data => new constructor({
|
|
transport: this,
|
|
client: this.client,
|
|
data: msgpack.decode(data),
|
|
}));
|
|
});
|
|
this.codec = codec;
|
|
return this.codec;
|
|
}
|
|
attach(writer, reader, client) {
|
|
this.encodeStream = this.encodeStream.pipe(writer);
|
|
const buffered = new buffered_1.default();
|
|
reader.pipe(buffered).pipe(this.decodeStream);
|
|
this.writer = writer;
|
|
this.reader = reader;
|
|
this.client = client;
|
|
this.attached = true;
|
|
}
|
|
detach() {
|
|
if (!this.attached)
|
|
return;
|
|
this.attached = false;
|
|
this.encodeStream.unpipe(this.writer);
|
|
this.reader.unpipe(this.decodeStream);
|
|
}
|
|
request(method, args, cb) {
|
|
if (!this.attached)
|
|
return cb([0, 'transport disconnected']);
|
|
this.nextRequestId = this.nextRequestId + 1;
|
|
this.debug('nvim request:', this.nextRequestId, method, args);
|
|
this.encodeStream.write(msgpack.encode([0, this.nextRequestId, method, args], {
|
|
codec: this.codec,
|
|
}));
|
|
this.pending.set(this.nextRequestId, cb);
|
|
}
|
|
notify(method, args) {
|
|
if (!this.attached)
|
|
return;
|
|
if (this._paused) {
|
|
this.paused.push([method, args]);
|
|
return;
|
|
}
|
|
this.debug('nvim notification:', method, args);
|
|
this.encodeStream.write(msgpack.encode([2, method, args], {
|
|
codec: this.codec,
|
|
}));
|
|
}
|
|
createResponse(requestId) {
|
|
let called = false;
|
|
let { encodeStream } = this;
|
|
return {
|
|
send: (resp, isError) => {
|
|
if (called || !this.attached)
|
|
return;
|
|
this.debug('response:', requestId, resp, isError == true);
|
|
called = true;
|
|
encodeStream.write(msgpack.encode([
|
|
1,
|
|
requestId,
|
|
isError ? resp : null,
|
|
!isError ? resp : null,
|
|
]));
|
|
}
|
|
};
|
|
}
|
|
}
|
|
exports.NvimTransport = NvimTransport;
|
|
|
|
|
|
/***/ }),
|
|
/* 9 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// msgpack.js
|
|
|
|
exports.encode = __webpack_require__(10).encode;
|
|
exports.decode = __webpack_require__(30).decode;
|
|
|
|
exports.Encoder = __webpack_require__(36).Encoder;
|
|
exports.Decoder = __webpack_require__(38).Decoder;
|
|
|
|
exports.createEncodeStream = __webpack_require__(39).createEncodeStream;
|
|
exports.createDecodeStream = __webpack_require__(42).createDecodeStream;
|
|
|
|
exports.createCodec = __webpack_require__(43).createCodec;
|
|
exports.codec = __webpack_require__(44).codec;
|
|
|
|
|
|
/***/ }),
|
|
/* 10 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// encode.js
|
|
|
|
exports.encode = encode;
|
|
|
|
var EncodeBuffer = __webpack_require__(11).EncodeBuffer;
|
|
|
|
function encode(input, options) {
|
|
var encoder = new EncodeBuffer(options);
|
|
encoder.write(input);
|
|
return encoder.read();
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 11 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// encode-buffer.js
|
|
|
|
exports.EncodeBuffer = EncodeBuffer;
|
|
|
|
var preset = __webpack_require__(12).preset;
|
|
|
|
var FlexEncoder = __webpack_require__(29).FlexEncoder;
|
|
|
|
FlexEncoder.mixin(EncodeBuffer.prototype);
|
|
|
|
function EncodeBuffer(options) {
|
|
if (!(this instanceof EncodeBuffer)) return new EncodeBuffer(options);
|
|
|
|
if (options) {
|
|
this.options = options;
|
|
if (options.codec) {
|
|
var codec = this.codec = options.codec;
|
|
if (codec.bufferish) this.bufferish = codec.bufferish;
|
|
}
|
|
}
|
|
}
|
|
|
|
EncodeBuffer.prototype.codec = preset;
|
|
|
|
EncodeBuffer.prototype.write = function(input) {
|
|
this.codec.encode(this, input);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 12 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// write-core.js
|
|
|
|
var ExtBuffer = __webpack_require__(13).ExtBuffer;
|
|
var ExtPacker = __webpack_require__(22);
|
|
var WriteType = __webpack_require__(23);
|
|
var CodecBase = __webpack_require__(28);
|
|
|
|
CodecBase.install({
|
|
addExtPacker: addExtPacker,
|
|
getExtPacker: getExtPacker,
|
|
init: init
|
|
});
|
|
|
|
exports.preset = init.call(CodecBase.preset);
|
|
|
|
function getEncoder(options) {
|
|
var writeType = WriteType.getWriteType(options);
|
|
return encode;
|
|
|
|
function encode(encoder, value) {
|
|
var func = writeType[typeof value];
|
|
if (!func) throw new Error("Unsupported type \"" + (typeof value) + "\": " + value);
|
|
func(encoder, value);
|
|
}
|
|
}
|
|
|
|
function init() {
|
|
var options = this.options;
|
|
this.encode = getEncoder(options);
|
|
|
|
if (options && options.preset) {
|
|
ExtPacker.setExtPackers(this);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
function addExtPacker(etype, Class, packer) {
|
|
packer = CodecBase.filter(packer);
|
|
var name = Class.name;
|
|
if (name && name !== "Object") {
|
|
var packers = this.extPackers || (this.extPackers = {});
|
|
packers[name] = extPacker;
|
|
} else {
|
|
// fallback for IE
|
|
var list = this.extEncoderList || (this.extEncoderList = []);
|
|
list.unshift([Class, extPacker]);
|
|
}
|
|
|
|
function extPacker(value) {
|
|
if (packer) value = packer(value);
|
|
return new ExtBuffer(value, etype);
|
|
}
|
|
}
|
|
|
|
function getExtPacker(value) {
|
|
var packers = this.extPackers || (this.extPackers = {});
|
|
var c = value.constructor;
|
|
var e = c && c.name && packers[c.name];
|
|
if (e) return e;
|
|
|
|
// fallback for IE
|
|
var list = this.extEncoderList || (this.extEncoderList = []);
|
|
var len = list.length;
|
|
for (var i = 0; i < len; i++) {
|
|
var pair = list[i];
|
|
if (c === pair[0]) return pair[1];
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 13 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// ext-buffer.js
|
|
|
|
exports.ExtBuffer = ExtBuffer;
|
|
|
|
var Bufferish = __webpack_require__(14);
|
|
|
|
function ExtBuffer(buffer, type) {
|
|
if (!(this instanceof ExtBuffer)) return new ExtBuffer(buffer, type);
|
|
this.buffer = Bufferish.from(buffer);
|
|
this.type = type;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 14 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// bufferish.js
|
|
|
|
var Buffer = exports.global = __webpack_require__(15);
|
|
var hasBuffer = exports.hasBuffer = Buffer && !!Buffer.isBuffer;
|
|
var hasArrayBuffer = exports.hasArrayBuffer = ("undefined" !== typeof ArrayBuffer);
|
|
|
|
var isArray = exports.isArray = __webpack_require__(16);
|
|
exports.isArrayBuffer = hasArrayBuffer ? isArrayBuffer : _false;
|
|
var isBuffer = exports.isBuffer = hasBuffer ? Buffer.isBuffer : _false;
|
|
var isView = exports.isView = hasArrayBuffer ? (ArrayBuffer.isView || _is("ArrayBuffer", "buffer")) : _false;
|
|
|
|
exports.alloc = alloc;
|
|
exports.concat = concat;
|
|
exports.from = from;
|
|
|
|
var BufferArray = exports.Array = __webpack_require__(17);
|
|
var BufferBuffer = exports.Buffer = __webpack_require__(18);
|
|
var BufferUint8Array = exports.Uint8Array = __webpack_require__(19);
|
|
var BufferProto = exports.prototype = __webpack_require__(20);
|
|
|
|
/**
|
|
* @param value {Array|ArrayBuffer|Buffer|String}
|
|
* @returns {Buffer|Uint8Array|Array}
|
|
*/
|
|
|
|
function from(value) {
|
|
if (typeof value === "string") {
|
|
return fromString.call(this, value);
|
|
} else {
|
|
return auto(this).from(value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param size {Number}
|
|
* @returns {Buffer|Uint8Array|Array}
|
|
*/
|
|
|
|
function alloc(size) {
|
|
return auto(this).alloc(size);
|
|
}
|
|
|
|
/**
|
|
* @param list {Array} array of (Buffer|Uint8Array|Array)s
|
|
* @param [length]
|
|
* @returns {Buffer|Uint8Array|Array}
|
|
*/
|
|
|
|
function concat(list, length) {
|
|
if (!length) {
|
|
length = 0;
|
|
Array.prototype.forEach.call(list, dryrun);
|
|
}
|
|
var ref = (this !== exports) && this || list[0];
|
|
var result = alloc.call(ref, length);
|
|
var offset = 0;
|
|
Array.prototype.forEach.call(list, append);
|
|
return result;
|
|
|
|
function dryrun(buffer) {
|
|
length += buffer.length;
|
|
}
|
|
|
|
function append(buffer) {
|
|
offset += BufferProto.copy.call(buffer, result, offset);
|
|
}
|
|
}
|
|
|
|
var _isArrayBuffer = _is("ArrayBuffer");
|
|
|
|
function isArrayBuffer(value) {
|
|
return (value instanceof ArrayBuffer) || _isArrayBuffer(value);
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
|
|
function fromString(value) {
|
|
var expected = value.length * 3;
|
|
var that = alloc.call(this, expected);
|
|
var actual = BufferProto.write.call(that, value);
|
|
if (expected !== actual) {
|
|
that = BufferProto.slice.call(that, 0, actual);
|
|
}
|
|
return that;
|
|
}
|
|
|
|
function auto(that) {
|
|
return isBuffer(that) ? BufferBuffer
|
|
: isView(that) ? BufferUint8Array
|
|
: isArray(that) ? BufferArray
|
|
: hasBuffer ? BufferBuffer
|
|
: hasArrayBuffer ? BufferUint8Array
|
|
: BufferArray;
|
|
}
|
|
|
|
function _false() {
|
|
return false;
|
|
}
|
|
|
|
function _is(name, key) {
|
|
/* jshint eqnull:true */
|
|
name = "[object " + name + "]";
|
|
return function(value) {
|
|
return (value != null) && {}.toString.call(key ? value[key] : value) === name;
|
|
};
|
|
}
|
|
|
|
/***/ }),
|
|
/* 15 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/* globals Buffer */
|
|
|
|
module.exports =
|
|
c(("undefined" !== typeof Buffer) && Buffer) ||
|
|
c(this.Buffer) ||
|
|
c(("undefined" !== typeof window) && window.Buffer) ||
|
|
this.Buffer;
|
|
|
|
function c(B) {
|
|
return B && B.isBuffer && B;
|
|
}
|
|
|
|
/***/ }),
|
|
/* 16 */
|
|
/***/ (function(module, exports) {
|
|
|
|
var toString = {}.toString;
|
|
|
|
module.exports = Array.isArray || function (arr) {
|
|
return toString.call(arr) == '[object Array]';
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 17 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// bufferish-array.js
|
|
|
|
var Bufferish = __webpack_require__(14);
|
|
|
|
var exports = module.exports = alloc(0);
|
|
|
|
exports.alloc = alloc;
|
|
exports.concat = Bufferish.concat;
|
|
exports.from = from;
|
|
|
|
/**
|
|
* @param size {Number}
|
|
* @returns {Buffer|Uint8Array|Array}
|
|
*/
|
|
|
|
function alloc(size) {
|
|
return new Array(size);
|
|
}
|
|
|
|
/**
|
|
* @param value {Array|ArrayBuffer|Buffer|String}
|
|
* @returns {Array}
|
|
*/
|
|
|
|
function from(value) {
|
|
if (!Bufferish.isBuffer(value) && Bufferish.isView(value)) {
|
|
// TypedArray to Uint8Array
|
|
value = Bufferish.Uint8Array.from(value);
|
|
} else if (Bufferish.isArrayBuffer(value)) {
|
|
// ArrayBuffer to Uint8Array
|
|
value = new Uint8Array(value);
|
|
} else if (typeof value === "string") {
|
|
// String to Array
|
|
return Bufferish.from.call(exports, value);
|
|
} else if (typeof value === "number") {
|
|
throw new TypeError('"value" argument must not be a number');
|
|
}
|
|
|
|
// Array-like to Array
|
|
return Array.prototype.slice.call(value);
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 18 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// bufferish-buffer.js
|
|
|
|
var Bufferish = __webpack_require__(14);
|
|
var Buffer = Bufferish.global;
|
|
|
|
var exports = module.exports = Bufferish.hasBuffer ? alloc(0) : [];
|
|
|
|
exports.alloc = Bufferish.hasBuffer && Buffer.alloc || alloc;
|
|
exports.concat = Bufferish.concat;
|
|
exports.from = from;
|
|
|
|
/**
|
|
* @param size {Number}
|
|
* @returns {Buffer|Uint8Array|Array}
|
|
*/
|
|
|
|
function alloc(size) {
|
|
return new Buffer(size);
|
|
}
|
|
|
|
/**
|
|
* @param value {Array|ArrayBuffer|Buffer|String}
|
|
* @returns {Buffer}
|
|
*/
|
|
|
|
function from(value) {
|
|
if (!Bufferish.isBuffer(value) && Bufferish.isView(value)) {
|
|
// TypedArray to Uint8Array
|
|
value = Bufferish.Uint8Array.from(value);
|
|
} else if (Bufferish.isArrayBuffer(value)) {
|
|
// ArrayBuffer to Uint8Array
|
|
value = new Uint8Array(value);
|
|
} else if (typeof value === "string") {
|
|
// String to Buffer
|
|
return Bufferish.from.call(exports, value);
|
|
} else if (typeof value === "number") {
|
|
throw new TypeError('"value" argument must not be a number');
|
|
}
|
|
|
|
// Array-like to Buffer
|
|
if (Buffer.from && Buffer.from.length !== 1) {
|
|
return Buffer.from(value); // node v6+
|
|
} else {
|
|
return new Buffer(value); // node v4
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 19 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// bufferish-uint8array.js
|
|
|
|
var Bufferish = __webpack_require__(14);
|
|
|
|
var exports = module.exports = Bufferish.hasArrayBuffer ? alloc(0) : [];
|
|
|
|
exports.alloc = alloc;
|
|
exports.concat = Bufferish.concat;
|
|
exports.from = from;
|
|
|
|
/**
|
|
* @param size {Number}
|
|
* @returns {Buffer|Uint8Array|Array}
|
|
*/
|
|
|
|
function alloc(size) {
|
|
return new Uint8Array(size);
|
|
}
|
|
|
|
/**
|
|
* @param value {Array|ArrayBuffer|Buffer|String}
|
|
* @returns {Uint8Array}
|
|
*/
|
|
|
|
function from(value) {
|
|
if (Bufferish.isView(value)) {
|
|
// TypedArray to ArrayBuffer
|
|
var byteOffset = value.byteOffset;
|
|
var byteLength = value.byteLength;
|
|
value = value.buffer;
|
|
if (value.byteLength !== byteLength) {
|
|
if (value.slice) {
|
|
value = value.slice(byteOffset, byteOffset + byteLength);
|
|
} else {
|
|
// Android 4.1 does not have ArrayBuffer.prototype.slice
|
|
value = new Uint8Array(value);
|
|
if (value.byteLength !== byteLength) {
|
|
// TypedArray to ArrayBuffer to Uint8Array to Array
|
|
value = Array.prototype.slice.call(value, byteOffset, byteOffset + byteLength);
|
|
}
|
|
}
|
|
}
|
|
} else if (typeof value === "string") {
|
|
// String to Uint8Array
|
|
return Bufferish.from.call(exports, value);
|
|
} else if (typeof value === "number") {
|
|
throw new TypeError('"value" argument must not be a number');
|
|
}
|
|
|
|
return new Uint8Array(value);
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 20 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// bufferish-proto.js
|
|
|
|
/* jshint eqnull:true */
|
|
|
|
var BufferLite = __webpack_require__(21);
|
|
|
|
exports.copy = copy;
|
|
exports.slice = slice;
|
|
exports.toString = toString;
|
|
exports.write = gen("write");
|
|
|
|
var Bufferish = __webpack_require__(14);
|
|
var Buffer = Bufferish.global;
|
|
|
|
var isBufferShim = Bufferish.hasBuffer && ("TYPED_ARRAY_SUPPORT" in Buffer);
|
|
var brokenTypedArray = isBufferShim && !Buffer.TYPED_ARRAY_SUPPORT;
|
|
|
|
/**
|
|
* @param target {Buffer|Uint8Array|Array}
|
|
* @param [targetStart] {Number}
|
|
* @param [start] {Number}
|
|
* @param [end] {Number}
|
|
* @returns {Buffer|Uint8Array|Array}
|
|
*/
|
|
|
|
function copy(target, targetStart, start, end) {
|
|
var thisIsBuffer = Bufferish.isBuffer(this);
|
|
var targetIsBuffer = Bufferish.isBuffer(target);
|
|
if (thisIsBuffer && targetIsBuffer) {
|
|
// Buffer to Buffer
|
|
return this.copy(target, targetStart, start, end);
|
|
} else if (!brokenTypedArray && !thisIsBuffer && !targetIsBuffer &&
|
|
Bufferish.isView(this) && Bufferish.isView(target)) {
|
|
// Uint8Array to Uint8Array (except for minor some browsers)
|
|
var buffer = (start || end != null) ? slice.call(this, start, end) : this;
|
|
target.set(buffer, targetStart);
|
|
return buffer.length;
|
|
} else {
|
|
// other cases
|
|
return BufferLite.copy.call(this, target, targetStart, start, end);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param [start] {Number}
|
|
* @param [end] {Number}
|
|
* @returns {Buffer|Uint8Array|Array}
|
|
*/
|
|
|
|
function slice(start, end) {
|
|
// for Buffer, Uint8Array (except for minor some browsers) and Array
|
|
var f = this.slice || (!brokenTypedArray && this.subarray);
|
|
if (f) return f.call(this, start, end);
|
|
|
|
// Uint8Array (for minor some browsers)
|
|
var target = Bufferish.alloc.call(this, end - start);
|
|
copy.call(this, target, 0, start, end);
|
|
return target;
|
|
}
|
|
|
|
/**
|
|
* Buffer.prototype.toString()
|
|
*
|
|
* @param [encoding] {String} ignored
|
|
* @param [start] {Number}
|
|
* @param [end] {Number}
|
|
* @returns {String}
|
|
*/
|
|
|
|
function toString(encoding, start, end) {
|
|
var f = (!isBufferShim && Bufferish.isBuffer(this)) ? this.toString : BufferLite.toString;
|
|
return f.apply(this, arguments);
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
|
|
function gen(method) {
|
|
return wrap;
|
|
|
|
function wrap() {
|
|
var f = this[method] || BufferLite[method];
|
|
return f.apply(this, arguments);
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 21 */
|
|
/***/ (function(module, exports) {
|
|
|
|
// buffer-lite.js
|
|
|
|
var MAXBUFLEN = 8192;
|
|
|
|
exports.copy = copy;
|
|
exports.toString = toString;
|
|
exports.write = write;
|
|
|
|
/**
|
|
* Buffer.prototype.write()
|
|
*
|
|
* @param string {String}
|
|
* @param [offset] {Number}
|
|
* @returns {Number}
|
|
*/
|
|
|
|
function write(string, offset) {
|
|
var buffer = this;
|
|
var index = offset || (offset |= 0);
|
|
var length = string.length;
|
|
var chr = 0;
|
|
var i = 0;
|
|
while (i < length) {
|
|
chr = string.charCodeAt(i++);
|
|
|
|
if (chr < 128) {
|
|
buffer[index++] = chr;
|
|
} else if (chr < 0x800) {
|
|
// 2 bytes
|
|
buffer[index++] = 0xC0 | (chr >>> 6);
|
|
buffer[index++] = 0x80 | (chr & 0x3F);
|
|
} else if (chr < 0xD800 || chr > 0xDFFF) {
|
|
// 3 bytes
|
|
buffer[index++] = 0xE0 | (chr >>> 12);
|
|
buffer[index++] = 0x80 | ((chr >>> 6) & 0x3F);
|
|
buffer[index++] = 0x80 | (chr & 0x3F);
|
|
} else {
|
|
// 4 bytes - surrogate pair
|
|
chr = (((chr - 0xD800) << 10) | (string.charCodeAt(i++) - 0xDC00)) + 0x10000;
|
|
buffer[index++] = 0xF0 | (chr >>> 18);
|
|
buffer[index++] = 0x80 | ((chr >>> 12) & 0x3F);
|
|
buffer[index++] = 0x80 | ((chr >>> 6) & 0x3F);
|
|
buffer[index++] = 0x80 | (chr & 0x3F);
|
|
}
|
|
}
|
|
return index - offset;
|
|
}
|
|
|
|
/**
|
|
* Buffer.prototype.toString()
|
|
*
|
|
* @param [encoding] {String} ignored
|
|
* @param [start] {Number}
|
|
* @param [end] {Number}
|
|
* @returns {String}
|
|
*/
|
|
|
|
function toString(encoding, start, end) {
|
|
var buffer = this;
|
|
var index = start|0;
|
|
if (!end) end = buffer.length;
|
|
var string = '';
|
|
var chr = 0;
|
|
|
|
while (index < end) {
|
|
chr = buffer[index++];
|
|
if (chr < 128) {
|
|
string += String.fromCharCode(chr);
|
|
continue;
|
|
}
|
|
|
|
if ((chr & 0xE0) === 0xC0) {
|
|
// 2 bytes
|
|
chr = (chr & 0x1F) << 6 |
|
|
(buffer[index++] & 0x3F);
|
|
|
|
} else if ((chr & 0xF0) === 0xE0) {
|
|
// 3 bytes
|
|
chr = (chr & 0x0F) << 12 |
|
|
(buffer[index++] & 0x3F) << 6 |
|
|
(buffer[index++] & 0x3F);
|
|
|
|
} else if ((chr & 0xF8) === 0xF0) {
|
|
// 4 bytes
|
|
chr = (chr & 0x07) << 18 |
|
|
(buffer[index++] & 0x3F) << 12 |
|
|
(buffer[index++] & 0x3F) << 6 |
|
|
(buffer[index++] & 0x3F);
|
|
}
|
|
|
|
if (chr >= 0x010000) {
|
|
// A surrogate pair
|
|
chr -= 0x010000;
|
|
|
|
string += String.fromCharCode((chr >>> 10) + 0xD800, (chr & 0x3FF) + 0xDC00);
|
|
} else {
|
|
string += String.fromCharCode(chr);
|
|
}
|
|
}
|
|
|
|
return string;
|
|
}
|
|
|
|
/**
|
|
* Buffer.prototype.copy()
|
|
*
|
|
* @param target {Buffer}
|
|
* @param [targetStart] {Number}
|
|
* @param [start] {Number}
|
|
* @param [end] {Number}
|
|
* @returns {number}
|
|
*/
|
|
|
|
function copy(target, targetStart, start, end) {
|
|
var i;
|
|
if (!start) start = 0;
|
|
if (!end && end !== 0) end = this.length;
|
|
if (!targetStart) targetStart = 0;
|
|
var len = end - start;
|
|
|
|
if (target === this && start < targetStart && targetStart < end) {
|
|
// descending
|
|
for (i = len - 1; i >= 0; i--) {
|
|
target[i + targetStart] = this[i + start];
|
|
}
|
|
} else {
|
|
// ascending
|
|
for (i = 0; i < len; i++) {
|
|
target[i + targetStart] = this[i + start];
|
|
}
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 22 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// ext-packer.js
|
|
|
|
exports.setExtPackers = setExtPackers;
|
|
|
|
var Bufferish = __webpack_require__(14);
|
|
var Buffer = Bufferish.global;
|
|
var packTypedArray = Bufferish.Uint8Array.from;
|
|
var _encode;
|
|
|
|
var ERROR_COLUMNS = {name: 1, message: 1, stack: 1, columnNumber: 1, fileName: 1, lineNumber: 1};
|
|
|
|
function setExtPackers(codec) {
|
|
codec.addExtPacker(0x0E, Error, [packError, encode]);
|
|
codec.addExtPacker(0x01, EvalError, [packError, encode]);
|
|
codec.addExtPacker(0x02, RangeError, [packError, encode]);
|
|
codec.addExtPacker(0x03, ReferenceError, [packError, encode]);
|
|
codec.addExtPacker(0x04, SyntaxError, [packError, encode]);
|
|
codec.addExtPacker(0x05, TypeError, [packError, encode]);
|
|
codec.addExtPacker(0x06, URIError, [packError, encode]);
|
|
|
|
codec.addExtPacker(0x0A, RegExp, [packRegExp, encode]);
|
|
codec.addExtPacker(0x0B, Boolean, [packValueOf, encode]);
|
|
codec.addExtPacker(0x0C, String, [packValueOf, encode]);
|
|
codec.addExtPacker(0x0D, Date, [Number, encode]);
|
|
codec.addExtPacker(0x0F, Number, [packValueOf, encode]);
|
|
|
|
if ("undefined" !== typeof Uint8Array) {
|
|
codec.addExtPacker(0x11, Int8Array, packTypedArray);
|
|
codec.addExtPacker(0x12, Uint8Array, packTypedArray);
|
|
codec.addExtPacker(0x13, Int16Array, packTypedArray);
|
|
codec.addExtPacker(0x14, Uint16Array, packTypedArray);
|
|
codec.addExtPacker(0x15, Int32Array, packTypedArray);
|
|
codec.addExtPacker(0x16, Uint32Array, packTypedArray);
|
|
codec.addExtPacker(0x17, Float32Array, packTypedArray);
|
|
|
|
// PhantomJS/1.9.7 doesn't have Float64Array
|
|
if ("undefined" !== typeof Float64Array) {
|
|
codec.addExtPacker(0x18, Float64Array, packTypedArray);
|
|
}
|
|
|
|
// IE10 doesn't have Uint8ClampedArray
|
|
if ("undefined" !== typeof Uint8ClampedArray) {
|
|
codec.addExtPacker(0x19, Uint8ClampedArray, packTypedArray);
|
|
}
|
|
|
|
codec.addExtPacker(0x1A, ArrayBuffer, packTypedArray);
|
|
codec.addExtPacker(0x1D, DataView, packTypedArray);
|
|
}
|
|
|
|
if (Bufferish.hasBuffer) {
|
|
codec.addExtPacker(0x1B, Buffer, Bufferish.from);
|
|
}
|
|
}
|
|
|
|
function encode(input) {
|
|
if (!_encode) _encode = __webpack_require__(10).encode; // lazy load
|
|
return _encode(input);
|
|
}
|
|
|
|
function packValueOf(value) {
|
|
return (value).valueOf();
|
|
}
|
|
|
|
function packRegExp(value) {
|
|
value = RegExp.prototype.toString.call(value).split("/");
|
|
value.shift();
|
|
var out = [value.pop()];
|
|
out.unshift(value.join("/"));
|
|
return out;
|
|
}
|
|
|
|
function packError(value) {
|
|
var out = {};
|
|
for (var key in ERROR_COLUMNS) {
|
|
out[key] = value[key];
|
|
}
|
|
return out;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 23 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// write-type.js
|
|
|
|
var IS_ARRAY = __webpack_require__(16);
|
|
var Int64Buffer = __webpack_require__(24);
|
|
var Uint64BE = Int64Buffer.Uint64BE;
|
|
var Int64BE = Int64Buffer.Int64BE;
|
|
|
|
var Bufferish = __webpack_require__(14);
|
|
var BufferProto = __webpack_require__(20);
|
|
var WriteToken = __webpack_require__(25);
|
|
var uint8 = __webpack_require__(27).uint8;
|
|
var ExtBuffer = __webpack_require__(13).ExtBuffer;
|
|
|
|
var HAS_UINT8ARRAY = ("undefined" !== typeof Uint8Array);
|
|
var HAS_MAP = ("undefined" !== typeof Map);
|
|
|
|
var extmap = [];
|
|
extmap[1] = 0xd4;
|
|
extmap[2] = 0xd5;
|
|
extmap[4] = 0xd6;
|
|
extmap[8] = 0xd7;
|
|
extmap[16] = 0xd8;
|
|
|
|
exports.getWriteType = getWriteType;
|
|
|
|
function getWriteType(options) {
|
|
var token = WriteToken.getWriteToken(options);
|
|
var useraw = options && options.useraw;
|
|
var binarraybuffer = HAS_UINT8ARRAY && options && options.binarraybuffer;
|
|
var isBuffer = binarraybuffer ? Bufferish.isArrayBuffer : Bufferish.isBuffer;
|
|
var bin = binarraybuffer ? bin_arraybuffer : bin_buffer;
|
|
var usemap = HAS_MAP && options && options.usemap;
|
|
var map = usemap ? map_to_map : obj_to_map;
|
|
|
|
var writeType = {
|
|
"boolean": bool,
|
|
"function": nil,
|
|
"number": number,
|
|
"object": (useraw ? object_raw : object),
|
|
"string": _string(useraw ? raw_head_size : str_head_size),
|
|
"symbol": nil,
|
|
"undefined": nil
|
|
};
|
|
|
|
return writeType;
|
|
|
|
// false -- 0xc2
|
|
// true -- 0xc3
|
|
function bool(encoder, value) {
|
|
var type = value ? 0xc3 : 0xc2;
|
|
token[type](encoder, value);
|
|
}
|
|
|
|
function number(encoder, value) {
|
|
var ivalue = value | 0;
|
|
var type;
|
|
if (value !== ivalue) {
|
|
// float 64 -- 0xcb
|
|
type = 0xcb;
|
|
token[type](encoder, value);
|
|
return;
|
|
} else if (-0x20 <= ivalue && ivalue <= 0x7F) {
|
|
// positive fixint -- 0x00 - 0x7f
|
|
// negative fixint -- 0xe0 - 0xff
|
|
type = ivalue & 0xFF;
|
|
} else if (0 <= ivalue) {
|
|
// uint 8 -- 0xcc
|
|
// uint 16 -- 0xcd
|
|
// uint 32 -- 0xce
|
|
type = (ivalue <= 0xFF) ? 0xcc : (ivalue <= 0xFFFF) ? 0xcd : 0xce;
|
|
} else {
|
|
// int 8 -- 0xd0
|
|
// int 16 -- 0xd1
|
|
// int 32 -- 0xd2
|
|
type = (-0x80 <= ivalue) ? 0xd0 : (-0x8000 <= ivalue) ? 0xd1 : 0xd2;
|
|
}
|
|
token[type](encoder, ivalue);
|
|
}
|
|
|
|
// uint 64 -- 0xcf
|
|
function uint64(encoder, value) {
|
|
var type = 0xcf;
|
|
token[type](encoder, value.toArray());
|
|
}
|
|
|
|
// int 64 -- 0xd3
|
|
function int64(encoder, value) {
|
|
var type = 0xd3;
|
|
token[type](encoder, value.toArray());
|
|
}
|
|
|
|
// str 8 -- 0xd9
|
|
// str 16 -- 0xda
|
|
// str 32 -- 0xdb
|
|
// fixstr -- 0xa0 - 0xbf
|
|
function str_head_size(length) {
|
|
return (length < 32) ? 1 : (length <= 0xFF) ? 2 : (length <= 0xFFFF) ? 3 : 5;
|
|
}
|
|
|
|
// raw 16 -- 0xda
|
|
// raw 32 -- 0xdb
|
|
// fixraw -- 0xa0 - 0xbf
|
|
function raw_head_size(length) {
|
|
return (length < 32) ? 1 : (length <= 0xFFFF) ? 3 : 5;
|
|
}
|
|
|
|
function _string(head_size) {
|
|
return string;
|
|
|
|
function string(encoder, value) {
|
|
// prepare buffer
|
|
var length = value.length;
|
|
var maxsize = 5 + length * 3;
|
|
encoder.offset = encoder.reserve(maxsize);
|
|
var buffer = encoder.buffer;
|
|
|
|
// expected header size
|
|
var expected = head_size(length);
|
|
|
|
// expected start point
|
|
var start = encoder.offset + expected;
|
|
|
|
// write string
|
|
length = BufferProto.write.call(buffer, value, start);
|
|
|
|
// actual header size
|
|
var actual = head_size(length);
|
|
|
|
// move content when needed
|
|
if (expected !== actual) {
|
|
var targetStart = start + actual - expected;
|
|
var end = start + length;
|
|
BufferProto.copy.call(buffer, buffer, targetStart, start, end);
|
|
}
|
|
|
|
// write header
|
|
var type = (actual === 1) ? (0xa0 + length) : (actual <= 3) ? (0xd7 + actual) : 0xdb;
|
|
token[type](encoder, length);
|
|
|
|
// move cursor
|
|
encoder.offset += length;
|
|
}
|
|
}
|
|
|
|
function object(encoder, value) {
|
|
// null
|
|
if (value === null) return nil(encoder, value);
|
|
|
|
// Buffer
|
|
if (isBuffer(value)) return bin(encoder, value);
|
|
|
|
// Array
|
|
if (IS_ARRAY(value)) return array(encoder, value);
|
|
|
|
// int64-buffer objects
|
|
if (Uint64BE.isUint64BE(value)) return uint64(encoder, value);
|
|
if (Int64BE.isInt64BE(value)) return int64(encoder, value);
|
|
|
|
// ext formats
|
|
var packer = encoder.codec.getExtPacker(value);
|
|
if (packer) value = packer(value);
|
|
if (value instanceof ExtBuffer) return ext(encoder, value);
|
|
|
|
// plain old Objects or Map
|
|
map(encoder, value);
|
|
}
|
|
|
|
function object_raw(encoder, value) {
|
|
// Buffer
|
|
if (isBuffer(value)) return raw(encoder, value);
|
|
|
|
// others
|
|
object(encoder, value);
|
|
}
|
|
|
|
// nil -- 0xc0
|
|
function nil(encoder, value) {
|
|
var type = 0xc0;
|
|
token[type](encoder, value);
|
|
}
|
|
|
|
// fixarray -- 0x90 - 0x9f
|
|
// array 16 -- 0xdc
|
|
// array 32 -- 0xdd
|
|
function array(encoder, value) {
|
|
var length = value.length;
|
|
var type = (length < 16) ? (0x90 + length) : (length <= 0xFFFF) ? 0xdc : 0xdd;
|
|
token[type](encoder, length);
|
|
|
|
var encode = encoder.codec.encode;
|
|
for (var i = 0; i < length; i++) {
|
|
encode(encoder, value[i]);
|
|
}
|
|
}
|
|
|
|
// bin 8 -- 0xc4
|
|
// bin 16 -- 0xc5
|
|
// bin 32 -- 0xc6
|
|
function bin_buffer(encoder, value) {
|
|
var length = value.length;
|
|
var type = (length < 0xFF) ? 0xc4 : (length <= 0xFFFF) ? 0xc5 : 0xc6;
|
|
token[type](encoder, length);
|
|
encoder.send(value);
|
|
}
|
|
|
|
function bin_arraybuffer(encoder, value) {
|
|
bin_buffer(encoder, new Uint8Array(value));
|
|
}
|
|
|
|
// fixext 1 -- 0xd4
|
|
// fixext 2 -- 0xd5
|
|
// fixext 4 -- 0xd6
|
|
// fixext 8 -- 0xd7
|
|
// fixext 16 -- 0xd8
|
|
// ext 8 -- 0xc7
|
|
// ext 16 -- 0xc8
|
|
// ext 32 -- 0xc9
|
|
function ext(encoder, value) {
|
|
var buffer = value.buffer;
|
|
var length = buffer.length;
|
|
var type = extmap[length] || ((length < 0xFF) ? 0xc7 : (length <= 0xFFFF) ? 0xc8 : 0xc9);
|
|
token[type](encoder, length);
|
|
uint8[value.type](encoder);
|
|
encoder.send(buffer);
|
|
}
|
|
|
|
// fixmap -- 0x80 - 0x8f
|
|
// map 16 -- 0xde
|
|
// map 32 -- 0xdf
|
|
function obj_to_map(encoder, value) {
|
|
var keys = Object.keys(value);
|
|
var length = keys.length;
|
|
var type = (length < 16) ? (0x80 + length) : (length <= 0xFFFF) ? 0xde : 0xdf;
|
|
token[type](encoder, length);
|
|
|
|
var encode = encoder.codec.encode;
|
|
keys.forEach(function(key) {
|
|
encode(encoder, key);
|
|
encode(encoder, value[key]);
|
|
});
|
|
}
|
|
|
|
// fixmap -- 0x80 - 0x8f
|
|
// map 16 -- 0xde
|
|
// map 32 -- 0xdf
|
|
function map_to_map(encoder, value) {
|
|
if (!(value instanceof Map)) return obj_to_map(encoder, value);
|
|
|
|
var length = value.size;
|
|
var type = (length < 16) ? (0x80 + length) : (length <= 0xFFFF) ? 0xde : 0xdf;
|
|
token[type](encoder, length);
|
|
|
|
var encode = encoder.codec.encode;
|
|
value.forEach(function(val, key, m) {
|
|
encode(encoder, key);
|
|
encode(encoder, val);
|
|
});
|
|
}
|
|
|
|
// raw 16 -- 0xda
|
|
// raw 32 -- 0xdb
|
|
// fixraw -- 0xa0 - 0xbf
|
|
function raw(encoder, value) {
|
|
var length = value.length;
|
|
var type = (length < 32) ? (0xa0 + length) : (length <= 0xFFFF) ? 0xda : 0xdb;
|
|
token[type](encoder, length);
|
|
encoder.send(value);
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 24 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// int64-buffer.js
|
|
|
|
/*jshint -W018 */ // Confusing use of '!'.
|
|
/*jshint -W030 */ // Expected an assignment or function call and instead saw an expression.
|
|
/*jshint -W093 */ // Did you mean to return a conditional instead of an assignment?
|
|
|
|
var Uint64BE, Int64BE, Uint64LE, Int64LE;
|
|
|
|
!function(exports) {
|
|
// constants
|
|
|
|
var UNDEFINED = "undefined";
|
|
var BUFFER = (UNDEFINED !== typeof Buffer) && Buffer;
|
|
var UINT8ARRAY = (UNDEFINED !== typeof Uint8Array) && Uint8Array;
|
|
var ARRAYBUFFER = (UNDEFINED !== typeof ArrayBuffer) && ArrayBuffer;
|
|
var ZERO = [0, 0, 0, 0, 0, 0, 0, 0];
|
|
var isArray = Array.isArray || _isArray;
|
|
var BIT32 = 4294967296;
|
|
var BIT24 = 16777216;
|
|
|
|
// storage class
|
|
|
|
var storage; // Array;
|
|
|
|
// generate classes
|
|
|
|
Uint64BE = factory("Uint64BE", true, true);
|
|
Int64BE = factory("Int64BE", true, false);
|
|
Uint64LE = factory("Uint64LE", false, true);
|
|
Int64LE = factory("Int64LE", false, false);
|
|
|
|
// class factory
|
|
|
|
function factory(name, bigendian, unsigned) {
|
|
var posH = bigendian ? 0 : 4;
|
|
var posL = bigendian ? 4 : 0;
|
|
var pos0 = bigendian ? 0 : 3;
|
|
var pos1 = bigendian ? 1 : 2;
|
|
var pos2 = bigendian ? 2 : 1;
|
|
var pos3 = bigendian ? 3 : 0;
|
|
var fromPositive = bigendian ? fromPositiveBE : fromPositiveLE;
|
|
var fromNegative = bigendian ? fromNegativeBE : fromNegativeLE;
|
|
var proto = Int64.prototype;
|
|
var isName = "is" + name;
|
|
var _isInt64 = "_" + isName;
|
|
|
|
// properties
|
|
proto.buffer = void 0;
|
|
proto.offset = 0;
|
|
proto[_isInt64] = true;
|
|
|
|
// methods
|
|
proto.toNumber = toNumber;
|
|
proto.toString = toString;
|
|
proto.toJSON = toNumber;
|
|
proto.toArray = toArray;
|
|
|
|
// add .toBuffer() method only when Buffer available
|
|
if (BUFFER) proto.toBuffer = toBuffer;
|
|
|
|
// add .toArrayBuffer() method only when Uint8Array available
|
|
if (UINT8ARRAY) proto.toArrayBuffer = toArrayBuffer;
|
|
|
|
// isUint64BE, isInt64BE
|
|
Int64[isName] = isInt64;
|
|
|
|
// CommonJS
|
|
exports[name] = Int64;
|
|
|
|
return Int64;
|
|
|
|
// constructor
|
|
function Int64(buffer, offset, value, raddix) {
|
|
if (!(this instanceof Int64)) return new Int64(buffer, offset, value, raddix);
|
|
return init(this, buffer, offset, value, raddix);
|
|
}
|
|
|
|
// isUint64BE, isInt64BE
|
|
function isInt64(b) {
|
|
return !!(b && b[_isInt64]);
|
|
}
|
|
|
|
// initializer
|
|
function init(that, buffer, offset, value, raddix) {
|
|
if (UINT8ARRAY && ARRAYBUFFER) {
|
|
if (buffer instanceof ARRAYBUFFER) buffer = new UINT8ARRAY(buffer);
|
|
if (value instanceof ARRAYBUFFER) value = new UINT8ARRAY(value);
|
|
}
|
|
|
|
// Int64BE() style
|
|
if (!buffer && !offset && !value && !storage) {
|
|
// shortcut to initialize with zero
|
|
that.buffer = newArray(ZERO, 0);
|
|
return;
|
|
}
|
|
|
|
// Int64BE(value, raddix) style
|
|
if (!isValidBuffer(buffer, offset)) {
|
|
var _storage = storage || Array;
|
|
raddix = offset;
|
|
value = buffer;
|
|
offset = 0;
|
|
buffer = new _storage(8);
|
|
}
|
|
|
|
that.buffer = buffer;
|
|
that.offset = offset |= 0;
|
|
|
|
// Int64BE(buffer, offset) style
|
|
if (UNDEFINED === typeof value) return;
|
|
|
|
// Int64BE(buffer, offset, value, raddix) style
|
|
if ("string" === typeof value) {
|
|
fromString(buffer, offset, value, raddix || 10);
|
|
} else if (isValidBuffer(value, raddix)) {
|
|
fromArray(buffer, offset, value, raddix);
|
|
} else if ("number" === typeof raddix) {
|
|
writeInt32(buffer, offset + posH, value); // high
|
|
writeInt32(buffer, offset + posL, raddix); // low
|
|
} else if (value > 0) {
|
|
fromPositive(buffer, offset, value); // positive
|
|
} else if (value < 0) {
|
|
fromNegative(buffer, offset, value); // negative
|
|
} else {
|
|
fromArray(buffer, offset, ZERO, 0); // zero, NaN and others
|
|
}
|
|
}
|
|
|
|
function fromString(buffer, offset, str, raddix) {
|
|
var pos = 0;
|
|
var len = str.length;
|
|
var high = 0;
|
|
var low = 0;
|
|
if (str[0] === "-") pos++;
|
|
var sign = pos;
|
|
while (pos < len) {
|
|
var chr = parseInt(str[pos++], raddix);
|
|
if (!(chr >= 0)) break; // NaN
|
|
low = low * raddix + chr;
|
|
high = high * raddix + Math.floor(low / BIT32);
|
|
low %= BIT32;
|
|
}
|
|
if (sign) {
|
|
high = ~high;
|
|
if (low) {
|
|
low = BIT32 - low;
|
|
} else {
|
|
high++;
|
|
}
|
|
}
|
|
writeInt32(buffer, offset + posH, high);
|
|
writeInt32(buffer, offset + posL, low);
|
|
}
|
|
|
|
function toNumber() {
|
|
var buffer = this.buffer;
|
|
var offset = this.offset;
|
|
var high = readInt32(buffer, offset + posH);
|
|
var low = readInt32(buffer, offset + posL);
|
|
if (!unsigned) high |= 0; // a trick to get signed
|
|
return high ? (high * BIT32 + low) : low;
|
|
}
|
|
|
|
function toString(radix) {
|
|
var buffer = this.buffer;
|
|
var offset = this.offset;
|
|
var high = readInt32(buffer, offset + posH);
|
|
var low = readInt32(buffer, offset + posL);
|
|
var str = "";
|
|
var sign = !unsigned && (high & 0x80000000);
|
|
if (sign) {
|
|
high = ~high;
|
|
low = BIT32 - low;
|
|
}
|
|
radix = radix || 10;
|
|
while (1) {
|
|
var mod = (high % radix) * BIT32 + low;
|
|
high = Math.floor(high / radix);
|
|
low = Math.floor(mod / radix);
|
|
str = (mod % radix).toString(radix) + str;
|
|
if (!high && !low) break;
|
|
}
|
|
if (sign) {
|
|
str = "-" + str;
|
|
}
|
|
return str;
|
|
}
|
|
|
|
function writeInt32(buffer, offset, value) {
|
|
buffer[offset + pos3] = value & 255;
|
|
value = value >> 8;
|
|
buffer[offset + pos2] = value & 255;
|
|
value = value >> 8;
|
|
buffer[offset + pos1] = value & 255;
|
|
value = value >> 8;
|
|
buffer[offset + pos0] = value & 255;
|
|
}
|
|
|
|
function readInt32(buffer, offset) {
|
|
return (buffer[offset + pos0] * BIT24) +
|
|
(buffer[offset + pos1] << 16) +
|
|
(buffer[offset + pos2] << 8) +
|
|
buffer[offset + pos3];
|
|
}
|
|
}
|
|
|
|
function toArray(raw) {
|
|
var buffer = this.buffer;
|
|
var offset = this.offset;
|
|
storage = null; // Array
|
|
if (raw !== false && offset === 0 && buffer.length === 8 && isArray(buffer)) return buffer;
|
|
return newArray(buffer, offset);
|
|
}
|
|
|
|
function toBuffer(raw) {
|
|
var buffer = this.buffer;
|
|
var offset = this.offset;
|
|
storage = BUFFER;
|
|
if (raw !== false && offset === 0 && buffer.length === 8 && Buffer.isBuffer(buffer)) return buffer;
|
|
var dest = new BUFFER(8);
|
|
fromArray(dest, 0, buffer, offset);
|
|
return dest;
|
|
}
|
|
|
|
function toArrayBuffer(raw) {
|
|
var buffer = this.buffer;
|
|
var offset = this.offset;
|
|
var arrbuf = buffer.buffer;
|
|
storage = UINT8ARRAY;
|
|
if (raw !== false && offset === 0 && (arrbuf instanceof ARRAYBUFFER) && arrbuf.byteLength === 8) return arrbuf;
|
|
var dest = new UINT8ARRAY(8);
|
|
fromArray(dest, 0, buffer, offset);
|
|
return dest.buffer;
|
|
}
|
|
|
|
function isValidBuffer(buffer, offset) {
|
|
var len = buffer && buffer.length;
|
|
offset |= 0;
|
|
return len && (offset + 8 <= len) && ("string" !== typeof buffer[offset]);
|
|
}
|
|
|
|
function fromArray(destbuf, destoff, srcbuf, srcoff) {
|
|
destoff |= 0;
|
|
srcoff |= 0;
|
|
for (var i = 0; i < 8; i++) {
|
|
destbuf[destoff++] = srcbuf[srcoff++] & 255;
|
|
}
|
|
}
|
|
|
|
function newArray(buffer, offset) {
|
|
return Array.prototype.slice.call(buffer, offset, offset + 8);
|
|
}
|
|
|
|
function fromPositiveBE(buffer, offset, value) {
|
|
var pos = offset + 8;
|
|
while (pos > offset) {
|
|
buffer[--pos] = value & 255;
|
|
value /= 256;
|
|
}
|
|
}
|
|
|
|
function fromNegativeBE(buffer, offset, value) {
|
|
var pos = offset + 8;
|
|
value++;
|
|
while (pos > offset) {
|
|
buffer[--pos] = ((-value) & 255) ^ 255;
|
|
value /= 256;
|
|
}
|
|
}
|
|
|
|
function fromPositiveLE(buffer, offset, value) {
|
|
var end = offset + 8;
|
|
while (offset < end) {
|
|
buffer[offset++] = value & 255;
|
|
value /= 256;
|
|
}
|
|
}
|
|
|
|
function fromNegativeLE(buffer, offset, value) {
|
|
var end = offset + 8;
|
|
value++;
|
|
while (offset < end) {
|
|
buffer[offset++] = ((-value) & 255) ^ 255;
|
|
value /= 256;
|
|
}
|
|
}
|
|
|
|
// https://github.com/retrofox/is-array
|
|
function _isArray(val) {
|
|
return !!val && "[object Array]" == Object.prototype.toString.call(val);
|
|
}
|
|
|
|
}( true && typeof exports.nodeName !== 'string' ? exports : (this || {}));
|
|
|
|
|
|
/***/ }),
|
|
/* 25 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// write-token.js
|
|
|
|
var ieee754 = __webpack_require__(26);
|
|
var Int64Buffer = __webpack_require__(24);
|
|
var Uint64BE = Int64Buffer.Uint64BE;
|
|
var Int64BE = Int64Buffer.Int64BE;
|
|
|
|
var uint8 = __webpack_require__(27).uint8;
|
|
var Bufferish = __webpack_require__(14);
|
|
var Buffer = Bufferish.global;
|
|
var IS_BUFFER_SHIM = Bufferish.hasBuffer && ("TYPED_ARRAY_SUPPORT" in Buffer);
|
|
var NO_TYPED_ARRAY = IS_BUFFER_SHIM && !Buffer.TYPED_ARRAY_SUPPORT;
|
|
var Buffer_prototype = Bufferish.hasBuffer && Buffer.prototype || {};
|
|
|
|
exports.getWriteToken = getWriteToken;
|
|
|
|
function getWriteToken(options) {
|
|
if (options && options.uint8array) {
|
|
return init_uint8array();
|
|
} else if (NO_TYPED_ARRAY || (Bufferish.hasBuffer && options && options.safe)) {
|
|
return init_safe();
|
|
} else {
|
|
return init_token();
|
|
}
|
|
}
|
|
|
|
function init_uint8array() {
|
|
var token = init_token();
|
|
|
|
// float 32 -- 0xca
|
|
// float 64 -- 0xcb
|
|
token[0xca] = writeN(0xca, 4, writeFloatBE);
|
|
token[0xcb] = writeN(0xcb, 8, writeDoubleBE);
|
|
|
|
return token;
|
|
}
|
|
|
|
// Node.js and browsers with TypedArray
|
|
|
|
function init_token() {
|
|
// (immediate values)
|
|
// positive fixint -- 0x00 - 0x7f
|
|
// nil -- 0xc0
|
|
// false -- 0xc2
|
|
// true -- 0xc3
|
|
// negative fixint -- 0xe0 - 0xff
|
|
var token = uint8.slice();
|
|
|
|
// bin 8 -- 0xc4
|
|
// bin 16 -- 0xc5
|
|
// bin 32 -- 0xc6
|
|
token[0xc4] = write1(0xc4);
|
|
token[0xc5] = write2(0xc5);
|
|
token[0xc6] = write4(0xc6);
|
|
|
|
// ext 8 -- 0xc7
|
|
// ext 16 -- 0xc8
|
|
// ext 32 -- 0xc9
|
|
token[0xc7] = write1(0xc7);
|
|
token[0xc8] = write2(0xc8);
|
|
token[0xc9] = write4(0xc9);
|
|
|
|
// float 32 -- 0xca
|
|
// float 64 -- 0xcb
|
|
token[0xca] = writeN(0xca, 4, (Buffer_prototype.writeFloatBE || writeFloatBE), true);
|
|
token[0xcb] = writeN(0xcb, 8, (Buffer_prototype.writeDoubleBE || writeDoubleBE), true);
|
|
|
|
// uint 8 -- 0xcc
|
|
// uint 16 -- 0xcd
|
|
// uint 32 -- 0xce
|
|
// uint 64 -- 0xcf
|
|
token[0xcc] = write1(0xcc);
|
|
token[0xcd] = write2(0xcd);
|
|
token[0xce] = write4(0xce);
|
|
token[0xcf] = writeN(0xcf, 8, writeUInt64BE);
|
|
|
|
// int 8 -- 0xd0
|
|
// int 16 -- 0xd1
|
|
// int 32 -- 0xd2
|
|
// int 64 -- 0xd3
|
|
token[0xd0] = write1(0xd0);
|
|
token[0xd1] = write2(0xd1);
|
|
token[0xd2] = write4(0xd2);
|
|
token[0xd3] = writeN(0xd3, 8, writeInt64BE);
|
|
|
|
// str 8 -- 0xd9
|
|
// str 16 -- 0xda
|
|
// str 32 -- 0xdb
|
|
token[0xd9] = write1(0xd9);
|
|
token[0xda] = write2(0xda);
|
|
token[0xdb] = write4(0xdb);
|
|
|
|
// array 16 -- 0xdc
|
|
// array 32 -- 0xdd
|
|
token[0xdc] = write2(0xdc);
|
|
token[0xdd] = write4(0xdd);
|
|
|
|
// map 16 -- 0xde
|
|
// map 32 -- 0xdf
|
|
token[0xde] = write2(0xde);
|
|
token[0xdf] = write4(0xdf);
|
|
|
|
return token;
|
|
}
|
|
|
|
// safe mode: for old browsers and who needs asserts
|
|
|
|
function init_safe() {
|
|
// (immediate values)
|
|
// positive fixint -- 0x00 - 0x7f
|
|
// nil -- 0xc0
|
|
// false -- 0xc2
|
|
// true -- 0xc3
|
|
// negative fixint -- 0xe0 - 0xff
|
|
var token = uint8.slice();
|
|
|
|
// bin 8 -- 0xc4
|
|
// bin 16 -- 0xc5
|
|
// bin 32 -- 0xc6
|
|
token[0xc4] = writeN(0xc4, 1, Buffer.prototype.writeUInt8);
|
|
token[0xc5] = writeN(0xc5, 2, Buffer.prototype.writeUInt16BE);
|
|
token[0xc6] = writeN(0xc6, 4, Buffer.prototype.writeUInt32BE);
|
|
|
|
// ext 8 -- 0xc7
|
|
// ext 16 -- 0xc8
|
|
// ext 32 -- 0xc9
|
|
token[0xc7] = writeN(0xc7, 1, Buffer.prototype.writeUInt8);
|
|
token[0xc8] = writeN(0xc8, 2, Buffer.prototype.writeUInt16BE);
|
|
token[0xc9] = writeN(0xc9, 4, Buffer.prototype.writeUInt32BE);
|
|
|
|
// float 32 -- 0xca
|
|
// float 64 -- 0xcb
|
|
token[0xca] = writeN(0xca, 4, Buffer.prototype.writeFloatBE);
|
|
token[0xcb] = writeN(0xcb, 8, Buffer.prototype.writeDoubleBE);
|
|
|
|
// uint 8 -- 0xcc
|
|
// uint 16 -- 0xcd
|
|
// uint 32 -- 0xce
|
|
// uint 64 -- 0xcf
|
|
token[0xcc] = writeN(0xcc, 1, Buffer.prototype.writeUInt8);
|
|
token[0xcd] = writeN(0xcd, 2, Buffer.prototype.writeUInt16BE);
|
|
token[0xce] = writeN(0xce, 4, Buffer.prototype.writeUInt32BE);
|
|
token[0xcf] = writeN(0xcf, 8, writeUInt64BE);
|
|
|
|
// int 8 -- 0xd0
|
|
// int 16 -- 0xd1
|
|
// int 32 -- 0xd2
|
|
// int 64 -- 0xd3
|
|
token[0xd0] = writeN(0xd0, 1, Buffer.prototype.writeInt8);
|
|
token[0xd1] = writeN(0xd1, 2, Buffer.prototype.writeInt16BE);
|
|
token[0xd2] = writeN(0xd2, 4, Buffer.prototype.writeInt32BE);
|
|
token[0xd3] = writeN(0xd3, 8, writeInt64BE);
|
|
|
|
// str 8 -- 0xd9
|
|
// str 16 -- 0xda
|
|
// str 32 -- 0xdb
|
|
token[0xd9] = writeN(0xd9, 1, Buffer.prototype.writeUInt8);
|
|
token[0xda] = writeN(0xda, 2, Buffer.prototype.writeUInt16BE);
|
|
token[0xdb] = writeN(0xdb, 4, Buffer.prototype.writeUInt32BE);
|
|
|
|
// array 16 -- 0xdc
|
|
// array 32 -- 0xdd
|
|
token[0xdc] = writeN(0xdc, 2, Buffer.prototype.writeUInt16BE);
|
|
token[0xdd] = writeN(0xdd, 4, Buffer.prototype.writeUInt32BE);
|
|
|
|
// map 16 -- 0xde
|
|
// map 32 -- 0xdf
|
|
token[0xde] = writeN(0xde, 2, Buffer.prototype.writeUInt16BE);
|
|
token[0xdf] = writeN(0xdf, 4, Buffer.prototype.writeUInt32BE);
|
|
|
|
return token;
|
|
}
|
|
|
|
function write1(type) {
|
|
return function(encoder, value) {
|
|
var offset = encoder.reserve(2);
|
|
var buffer = encoder.buffer;
|
|
buffer[offset++] = type;
|
|
buffer[offset] = value;
|
|
};
|
|
}
|
|
|
|
function write2(type) {
|
|
return function(encoder, value) {
|
|
var offset = encoder.reserve(3);
|
|
var buffer = encoder.buffer;
|
|
buffer[offset++] = type;
|
|
buffer[offset++] = value >>> 8;
|
|
buffer[offset] = value;
|
|
};
|
|
}
|
|
|
|
function write4(type) {
|
|
return function(encoder, value) {
|
|
var offset = encoder.reserve(5);
|
|
var buffer = encoder.buffer;
|
|
buffer[offset++] = type;
|
|
buffer[offset++] = value >>> 24;
|
|
buffer[offset++] = value >>> 16;
|
|
buffer[offset++] = value >>> 8;
|
|
buffer[offset] = value;
|
|
};
|
|
}
|
|
|
|
function writeN(type, len, method, noAssert) {
|
|
return function(encoder, value) {
|
|
var offset = encoder.reserve(len + 1);
|
|
encoder.buffer[offset++] = type;
|
|
method.call(encoder.buffer, value, offset, noAssert);
|
|
};
|
|
}
|
|
|
|
function writeUInt64BE(value, offset) {
|
|
new Uint64BE(this, offset, value);
|
|
}
|
|
|
|
function writeInt64BE(value, offset) {
|
|
new Int64BE(this, offset, value);
|
|
}
|
|
|
|
function writeFloatBE(value, offset) {
|
|
ieee754.write(this, value, offset, false, 23, 4);
|
|
}
|
|
|
|
function writeDoubleBE(value, offset) {
|
|
ieee754.write(this, value, offset, false, 52, 8);
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 26 */
|
|
/***/ (function(module, exports) {
|
|
|
|
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
|
|
var e, m
|
|
var eLen = (nBytes * 8) - mLen - 1
|
|
var eMax = (1 << eLen) - 1
|
|
var eBias = eMax >> 1
|
|
var nBits = -7
|
|
var i = isLE ? (nBytes - 1) : 0
|
|
var d = isLE ? -1 : 1
|
|
var s = buffer[offset + i]
|
|
|
|
i += d
|
|
|
|
e = s & ((1 << (-nBits)) - 1)
|
|
s >>= (-nBits)
|
|
nBits += eLen
|
|
for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}
|
|
|
|
m = e & ((1 << (-nBits)) - 1)
|
|
e >>= (-nBits)
|
|
nBits += mLen
|
|
for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}
|
|
|
|
if (e === 0) {
|
|
e = 1 - eBias
|
|
} else if (e === eMax) {
|
|
return m ? NaN : ((s ? -1 : 1) * Infinity)
|
|
} else {
|
|
m = m + Math.pow(2, mLen)
|
|
e = e - eBias
|
|
}
|
|
return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
|
|
}
|
|
|
|
exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
|
|
var e, m, c
|
|
var eLen = (nBytes * 8) - mLen - 1
|
|
var eMax = (1 << eLen) - 1
|
|
var eBias = eMax >> 1
|
|
var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
|
|
var i = isLE ? 0 : (nBytes - 1)
|
|
var d = isLE ? 1 : -1
|
|
var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
|
|
|
|
value = Math.abs(value)
|
|
|
|
if (isNaN(value) || value === Infinity) {
|
|
m = isNaN(value) ? 1 : 0
|
|
e = eMax
|
|
} else {
|
|
e = Math.floor(Math.log(value) / Math.LN2)
|
|
if (value * (c = Math.pow(2, -e)) < 1) {
|
|
e--
|
|
c *= 2
|
|
}
|
|
if (e + eBias >= 1) {
|
|
value += rt / c
|
|
} else {
|
|
value += rt * Math.pow(2, 1 - eBias)
|
|
}
|
|
if (value * c >= 2) {
|
|
e++
|
|
c /= 2
|
|
}
|
|
|
|
if (e + eBias >= eMax) {
|
|
m = 0
|
|
e = eMax
|
|
} else if (e + eBias >= 1) {
|
|
m = ((value * c) - 1) * Math.pow(2, mLen)
|
|
e = e + eBias
|
|
} else {
|
|
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
|
|
e = 0
|
|
}
|
|
}
|
|
|
|
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
|
|
|
|
e = (e << mLen) | m
|
|
eLen += mLen
|
|
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
|
|
|
|
buffer[offset + i - d] |= s * 128
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 27 */
|
|
/***/ (function(module, exports) {
|
|
|
|
// write-unit8.js
|
|
|
|
var constant = exports.uint8 = new Array(256);
|
|
|
|
for (var i = 0x00; i <= 0xFF; i++) {
|
|
constant[i] = write0(i);
|
|
}
|
|
|
|
function write0(type) {
|
|
return function(encoder) {
|
|
var offset = encoder.reserve(1);
|
|
encoder.buffer[offset] = type;
|
|
};
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 28 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// codec-base.js
|
|
|
|
var IS_ARRAY = __webpack_require__(16);
|
|
|
|
exports.createCodec = createCodec;
|
|
exports.install = install;
|
|
exports.filter = filter;
|
|
|
|
var Bufferish = __webpack_require__(14);
|
|
|
|
function Codec(options) {
|
|
if (!(this instanceof Codec)) return new Codec(options);
|
|
this.options = options;
|
|
this.init();
|
|
}
|
|
|
|
Codec.prototype.init = function() {
|
|
var options = this.options;
|
|
|
|
if (options && options.uint8array) {
|
|
this.bufferish = Bufferish.Uint8Array;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
function install(props) {
|
|
for (var key in props) {
|
|
Codec.prototype[key] = add(Codec.prototype[key], props[key]);
|
|
}
|
|
}
|
|
|
|
function add(a, b) {
|
|
return (a && b) ? ab : (a || b);
|
|
|
|
function ab() {
|
|
a.apply(this, arguments);
|
|
return b.apply(this, arguments);
|
|
}
|
|
}
|
|
|
|
function join(filters) {
|
|
filters = filters.slice();
|
|
|
|
return function(value) {
|
|
return filters.reduce(iterator, value);
|
|
};
|
|
|
|
function iterator(value, filter) {
|
|
return filter(value);
|
|
}
|
|
}
|
|
|
|
function filter(filter) {
|
|
return IS_ARRAY(filter) ? join(filter) : filter;
|
|
}
|
|
|
|
// @public
|
|
// msgpack.createCodec()
|
|
|
|
function createCodec(options) {
|
|
return new Codec(options);
|
|
}
|
|
|
|
// default shared codec
|
|
|
|
exports.preset = createCodec({preset: true});
|
|
|
|
|
|
/***/ }),
|
|
/* 29 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// flex-buffer.js
|
|
|
|
exports.FlexDecoder = FlexDecoder;
|
|
exports.FlexEncoder = FlexEncoder;
|
|
|
|
var Bufferish = __webpack_require__(14);
|
|
|
|
var MIN_BUFFER_SIZE = 2048;
|
|
var MAX_BUFFER_SIZE = 65536;
|
|
var BUFFER_SHORTAGE = "BUFFER_SHORTAGE";
|
|
|
|
function FlexDecoder() {
|
|
if (!(this instanceof FlexDecoder)) return new FlexDecoder();
|
|
}
|
|
|
|
function FlexEncoder() {
|
|
if (!(this instanceof FlexEncoder)) return new FlexEncoder();
|
|
}
|
|
|
|
FlexDecoder.mixin = mixinFactory(getDecoderMethods());
|
|
FlexDecoder.mixin(FlexDecoder.prototype);
|
|
|
|
FlexEncoder.mixin = mixinFactory(getEncoderMethods());
|
|
FlexEncoder.mixin(FlexEncoder.prototype);
|
|
|
|
function getDecoderMethods() {
|
|
return {
|
|
bufferish: Bufferish,
|
|
write: write,
|
|
fetch: fetch,
|
|
flush: flush,
|
|
push: push,
|
|
pull: pull,
|
|
read: read,
|
|
reserve: reserve,
|
|
offset: 0
|
|
};
|
|
|
|
function write(chunk) {
|
|
var prev = this.offset ? Bufferish.prototype.slice.call(this.buffer, this.offset) : this.buffer;
|
|
this.buffer = prev ? (chunk ? this.bufferish.concat([prev, chunk]) : prev) : chunk;
|
|
this.offset = 0;
|
|
}
|
|
|
|
function flush() {
|
|
while (this.offset < this.buffer.length) {
|
|
var start = this.offset;
|
|
var value;
|
|
try {
|
|
value = this.fetch();
|
|
} catch (e) {
|
|
if (e && e.message != BUFFER_SHORTAGE) throw e;
|
|
// rollback
|
|
this.offset = start;
|
|
break;
|
|
}
|
|
this.push(value);
|
|
}
|
|
}
|
|
|
|
function reserve(length) {
|
|
var start = this.offset;
|
|
var end = start + length;
|
|
if (end > this.buffer.length) throw new Error(BUFFER_SHORTAGE);
|
|
this.offset = end;
|
|
return start;
|
|
}
|
|
}
|
|
|
|
function getEncoderMethods() {
|
|
return {
|
|
bufferish: Bufferish,
|
|
write: write,
|
|
fetch: fetch,
|
|
flush: flush,
|
|
push: push,
|
|
pull: pull,
|
|
read: read,
|
|
reserve: reserve,
|
|
send: send,
|
|
maxBufferSize: MAX_BUFFER_SIZE,
|
|
minBufferSize: MIN_BUFFER_SIZE,
|
|
offset: 0,
|
|
start: 0
|
|
};
|
|
|
|
function fetch() {
|
|
var start = this.start;
|
|
if (start < this.offset) {
|
|
var end = this.start = this.offset;
|
|
return Bufferish.prototype.slice.call(this.buffer, start, end);
|
|
}
|
|
}
|
|
|
|
function flush() {
|
|
while (this.start < this.offset) {
|
|
var value = this.fetch();
|
|
if (value) this.push(value);
|
|
}
|
|
}
|
|
|
|
function pull() {
|
|
var buffers = this.buffers || (this.buffers = []);
|
|
var chunk = buffers.length > 1 ? this.bufferish.concat(buffers) : buffers[0];
|
|
buffers.length = 0; // buffer exhausted
|
|
return chunk;
|
|
}
|
|
|
|
function reserve(length) {
|
|
var req = length | 0;
|
|
|
|
if (this.buffer) {
|
|
var size = this.buffer.length;
|
|
var start = this.offset | 0;
|
|
var end = start + req;
|
|
|
|
// is it long enough?
|
|
if (end < size) {
|
|
this.offset = end;
|
|
return start;
|
|
}
|
|
|
|
// flush current buffer
|
|
this.flush();
|
|
|
|
// resize it to 2x current length
|
|
length = Math.max(length, Math.min(size * 2, this.maxBufferSize));
|
|
}
|
|
|
|
// minimum buffer size
|
|
length = Math.max(length, this.minBufferSize);
|
|
|
|
// allocate new buffer
|
|
this.buffer = this.bufferish.alloc(length);
|
|
this.start = 0;
|
|
this.offset = req;
|
|
return 0;
|
|
}
|
|
|
|
function send(buffer) {
|
|
var length = buffer.length;
|
|
if (length > this.minBufferSize) {
|
|
this.flush();
|
|
this.push(buffer);
|
|
} else {
|
|
var offset = this.reserve(length);
|
|
Bufferish.prototype.copy.call(buffer, this.buffer, offset);
|
|
}
|
|
}
|
|
}
|
|
|
|
// common methods
|
|
|
|
function write() {
|
|
throw new Error("method not implemented: write()");
|
|
}
|
|
|
|
function fetch() {
|
|
throw new Error("method not implemented: fetch()");
|
|
}
|
|
|
|
function read() {
|
|
var length = this.buffers && this.buffers.length;
|
|
|
|
// fetch the first result
|
|
if (!length) return this.fetch();
|
|
|
|
// flush current buffer
|
|
this.flush();
|
|
|
|
// read from the results
|
|
return this.pull();
|
|
}
|
|
|
|
function push(chunk) {
|
|
var buffers = this.buffers || (this.buffers = []);
|
|
buffers.push(chunk);
|
|
}
|
|
|
|
function pull() {
|
|
var buffers = this.buffers || (this.buffers = []);
|
|
return buffers.shift();
|
|
}
|
|
|
|
function mixinFactory(source) {
|
|
return mixin;
|
|
|
|
function mixin(target) {
|
|
for (var key in source) {
|
|
target[key] = source[key];
|
|
}
|
|
return target;
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 30 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// decode.js
|
|
|
|
exports.decode = decode;
|
|
|
|
var DecodeBuffer = __webpack_require__(31).DecodeBuffer;
|
|
|
|
function decode(input, options) {
|
|
var decoder = new DecodeBuffer(options);
|
|
decoder.write(input);
|
|
return decoder.read();
|
|
}
|
|
|
|
/***/ }),
|
|
/* 31 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// decode-buffer.js
|
|
|
|
exports.DecodeBuffer = DecodeBuffer;
|
|
|
|
var preset = __webpack_require__(32).preset;
|
|
|
|
var FlexDecoder = __webpack_require__(29).FlexDecoder;
|
|
|
|
FlexDecoder.mixin(DecodeBuffer.prototype);
|
|
|
|
function DecodeBuffer(options) {
|
|
if (!(this instanceof DecodeBuffer)) return new DecodeBuffer(options);
|
|
|
|
if (options) {
|
|
this.options = options;
|
|
if (options.codec) {
|
|
var codec = this.codec = options.codec;
|
|
if (codec.bufferish) this.bufferish = codec.bufferish;
|
|
}
|
|
}
|
|
}
|
|
|
|
DecodeBuffer.prototype.codec = preset;
|
|
|
|
DecodeBuffer.prototype.fetch = function() {
|
|
return this.codec.decode(this);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 32 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// read-core.js
|
|
|
|
var ExtBuffer = __webpack_require__(13).ExtBuffer;
|
|
var ExtUnpacker = __webpack_require__(33);
|
|
var readUint8 = __webpack_require__(34).readUint8;
|
|
var ReadToken = __webpack_require__(35);
|
|
var CodecBase = __webpack_require__(28);
|
|
|
|
CodecBase.install({
|
|
addExtUnpacker: addExtUnpacker,
|
|
getExtUnpacker: getExtUnpacker,
|
|
init: init
|
|
});
|
|
|
|
exports.preset = init.call(CodecBase.preset);
|
|
|
|
function getDecoder(options) {
|
|
var readToken = ReadToken.getReadToken(options);
|
|
return decode;
|
|
|
|
function decode(decoder) {
|
|
var type = readUint8(decoder);
|
|
var func = readToken[type];
|
|
if (!func) throw new Error("Invalid type: " + (type ? ("0x" + type.toString(16)) : type));
|
|
return func(decoder);
|
|
}
|
|
}
|
|
|
|
function init() {
|
|
var options = this.options;
|
|
this.decode = getDecoder(options);
|
|
|
|
if (options && options.preset) {
|
|
ExtUnpacker.setExtUnpackers(this);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
function addExtUnpacker(etype, unpacker) {
|
|
var unpackers = this.extUnpackers || (this.extUnpackers = []);
|
|
unpackers[etype] = CodecBase.filter(unpacker);
|
|
}
|
|
|
|
function getExtUnpacker(type) {
|
|
var unpackers = this.extUnpackers || (this.extUnpackers = []);
|
|
return unpackers[type] || extUnpacker;
|
|
|
|
function extUnpacker(buffer) {
|
|
return new ExtBuffer(buffer, type);
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 33 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// ext-unpacker.js
|
|
|
|
exports.setExtUnpackers = setExtUnpackers;
|
|
|
|
var Bufferish = __webpack_require__(14);
|
|
var Buffer = Bufferish.global;
|
|
var _decode;
|
|
|
|
var ERROR_COLUMNS = {name: 1, message: 1, stack: 1, columnNumber: 1, fileName: 1, lineNumber: 1};
|
|
|
|
function setExtUnpackers(codec) {
|
|
codec.addExtUnpacker(0x0E, [decode, unpackError(Error)]);
|
|
codec.addExtUnpacker(0x01, [decode, unpackError(EvalError)]);
|
|
codec.addExtUnpacker(0x02, [decode, unpackError(RangeError)]);
|
|
codec.addExtUnpacker(0x03, [decode, unpackError(ReferenceError)]);
|
|
codec.addExtUnpacker(0x04, [decode, unpackError(SyntaxError)]);
|
|
codec.addExtUnpacker(0x05, [decode, unpackError(TypeError)]);
|
|
codec.addExtUnpacker(0x06, [decode, unpackError(URIError)]);
|
|
|
|
codec.addExtUnpacker(0x0A, [decode, unpackRegExp]);
|
|
codec.addExtUnpacker(0x0B, [decode, unpackClass(Boolean)]);
|
|
codec.addExtUnpacker(0x0C, [decode, unpackClass(String)]);
|
|
codec.addExtUnpacker(0x0D, [decode, unpackClass(Date)]);
|
|
codec.addExtUnpacker(0x0F, [decode, unpackClass(Number)]);
|
|
|
|
if ("undefined" !== typeof Uint8Array) {
|
|
codec.addExtUnpacker(0x11, unpackClass(Int8Array));
|
|
codec.addExtUnpacker(0x12, unpackClass(Uint8Array));
|
|
codec.addExtUnpacker(0x13, [unpackArrayBuffer, unpackClass(Int16Array)]);
|
|
codec.addExtUnpacker(0x14, [unpackArrayBuffer, unpackClass(Uint16Array)]);
|
|
codec.addExtUnpacker(0x15, [unpackArrayBuffer, unpackClass(Int32Array)]);
|
|
codec.addExtUnpacker(0x16, [unpackArrayBuffer, unpackClass(Uint32Array)]);
|
|
codec.addExtUnpacker(0x17, [unpackArrayBuffer, unpackClass(Float32Array)]);
|
|
|
|
// PhantomJS/1.9.7 doesn't have Float64Array
|
|
if ("undefined" !== typeof Float64Array) {
|
|
codec.addExtUnpacker(0x18, [unpackArrayBuffer, unpackClass(Float64Array)]);
|
|
}
|
|
|
|
// IE10 doesn't have Uint8ClampedArray
|
|
if ("undefined" !== typeof Uint8ClampedArray) {
|
|
codec.addExtUnpacker(0x19, unpackClass(Uint8ClampedArray));
|
|
}
|
|
|
|
codec.addExtUnpacker(0x1A, unpackArrayBuffer);
|
|
codec.addExtUnpacker(0x1D, [unpackArrayBuffer, unpackClass(DataView)]);
|
|
}
|
|
|
|
if (Bufferish.hasBuffer) {
|
|
codec.addExtUnpacker(0x1B, unpackClass(Buffer));
|
|
}
|
|
}
|
|
|
|
function decode(input) {
|
|
if (!_decode) _decode = __webpack_require__(30).decode; // lazy load
|
|
return _decode(input);
|
|
}
|
|
|
|
function unpackRegExp(value) {
|
|
return RegExp.apply(null, value);
|
|
}
|
|
|
|
function unpackError(Class) {
|
|
return function(value) {
|
|
var out = new Class();
|
|
for (var key in ERROR_COLUMNS) {
|
|
out[key] = value[key];
|
|
}
|
|
return out;
|
|
};
|
|
}
|
|
|
|
function unpackClass(Class) {
|
|
return function(value) {
|
|
return new Class(value);
|
|
};
|
|
}
|
|
|
|
function unpackArrayBuffer(value) {
|
|
return (new Uint8Array(value)).buffer;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 34 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// read-format.js
|
|
|
|
var ieee754 = __webpack_require__(26);
|
|
var Int64Buffer = __webpack_require__(24);
|
|
var Uint64BE = Int64Buffer.Uint64BE;
|
|
var Int64BE = Int64Buffer.Int64BE;
|
|
|
|
exports.getReadFormat = getReadFormat;
|
|
exports.readUint8 = uint8;
|
|
|
|
var Bufferish = __webpack_require__(14);
|
|
var BufferProto = __webpack_require__(20);
|
|
|
|
var HAS_MAP = ("undefined" !== typeof Map);
|
|
var NO_ASSERT = true;
|
|
|
|
function getReadFormat(options) {
|
|
var binarraybuffer = Bufferish.hasArrayBuffer && options && options.binarraybuffer;
|
|
var int64 = options && options.int64;
|
|
var usemap = HAS_MAP && options && options.usemap;
|
|
|
|
var readFormat = {
|
|
map: (usemap ? map_to_map : map_to_obj),
|
|
array: array,
|
|
str: str,
|
|
bin: (binarraybuffer ? bin_arraybuffer : bin_buffer),
|
|
ext: ext,
|
|
uint8: uint8,
|
|
uint16: uint16,
|
|
uint32: uint32,
|
|
uint64: read(8, int64 ? readUInt64BE_int64 : readUInt64BE),
|
|
int8: int8,
|
|
int16: int16,
|
|
int32: int32,
|
|
int64: read(8, int64 ? readInt64BE_int64 : readInt64BE),
|
|
float32: read(4, readFloatBE),
|
|
float64: read(8, readDoubleBE)
|
|
};
|
|
|
|
return readFormat;
|
|
}
|
|
|
|
function map_to_obj(decoder, len) {
|
|
var value = {};
|
|
var i;
|
|
var k = new Array(len);
|
|
var v = new Array(len);
|
|
|
|
var decode = decoder.codec.decode;
|
|
for (i = 0; i < len; i++) {
|
|
k[i] = decode(decoder);
|
|
v[i] = decode(decoder);
|
|
}
|
|
for (i = 0; i < len; i++) {
|
|
value[k[i]] = v[i];
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function map_to_map(decoder, len) {
|
|
var value = new Map();
|
|
var i;
|
|
var k = new Array(len);
|
|
var v = new Array(len);
|
|
|
|
var decode = decoder.codec.decode;
|
|
for (i = 0; i < len; i++) {
|
|
k[i] = decode(decoder);
|
|
v[i] = decode(decoder);
|
|
}
|
|
for (i = 0; i < len; i++) {
|
|
value.set(k[i], v[i]);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function array(decoder, len) {
|
|
var value = new Array(len);
|
|
var decode = decoder.codec.decode;
|
|
for (var i = 0; i < len; i++) {
|
|
value[i] = decode(decoder);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function str(decoder, len) {
|
|
var start = decoder.reserve(len);
|
|
var end = start + len;
|
|
return BufferProto.toString.call(decoder.buffer, "utf-8", start, end);
|
|
}
|
|
|
|
function bin_buffer(decoder, len) {
|
|
var start = decoder.reserve(len);
|
|
var end = start + len;
|
|
var buf = BufferProto.slice.call(decoder.buffer, start, end);
|
|
return Bufferish.from(buf);
|
|
}
|
|
|
|
function bin_arraybuffer(decoder, len) {
|
|
var start = decoder.reserve(len);
|
|
var end = start + len;
|
|
var buf = BufferProto.slice.call(decoder.buffer, start, end);
|
|
return Bufferish.Uint8Array.from(buf).buffer;
|
|
}
|
|
|
|
function ext(decoder, len) {
|
|
var start = decoder.reserve(len+1);
|
|
var type = decoder.buffer[start++];
|
|
var end = start + len;
|
|
var unpack = decoder.codec.getExtUnpacker(type);
|
|
if (!unpack) throw new Error("Invalid ext type: " + (type ? ("0x" + type.toString(16)) : type));
|
|
var buf = BufferProto.slice.call(decoder.buffer, start, end);
|
|
return unpack(buf);
|
|
}
|
|
|
|
function uint8(decoder) {
|
|
var start = decoder.reserve(1);
|
|
return decoder.buffer[start];
|
|
}
|
|
|
|
function int8(decoder) {
|
|
var start = decoder.reserve(1);
|
|
var value = decoder.buffer[start];
|
|
return (value & 0x80) ? value - 0x100 : value;
|
|
}
|
|
|
|
function uint16(decoder) {
|
|
var start = decoder.reserve(2);
|
|
var buffer = decoder.buffer;
|
|
return (buffer[start++] << 8) | buffer[start];
|
|
}
|
|
|
|
function int16(decoder) {
|
|
var start = decoder.reserve(2);
|
|
var buffer = decoder.buffer;
|
|
var value = (buffer[start++] << 8) | buffer[start];
|
|
return (value & 0x8000) ? value - 0x10000 : value;
|
|
}
|
|
|
|
function uint32(decoder) {
|
|
var start = decoder.reserve(4);
|
|
var buffer = decoder.buffer;
|
|
return (buffer[start++] * 16777216) + (buffer[start++] << 16) + (buffer[start++] << 8) + buffer[start];
|
|
}
|
|
|
|
function int32(decoder) {
|
|
var start = decoder.reserve(4);
|
|
var buffer = decoder.buffer;
|
|
return (buffer[start++] << 24) | (buffer[start++] << 16) | (buffer[start++] << 8) | buffer[start];
|
|
}
|
|
|
|
function read(len, method) {
|
|
return function(decoder) {
|
|
var start = decoder.reserve(len);
|
|
return method.call(decoder.buffer, start, NO_ASSERT);
|
|
};
|
|
}
|
|
|
|
function readUInt64BE(start) {
|
|
return new Uint64BE(this, start).toNumber();
|
|
}
|
|
|
|
function readInt64BE(start) {
|
|
return new Int64BE(this, start).toNumber();
|
|
}
|
|
|
|
function readUInt64BE_int64(start) {
|
|
return new Uint64BE(this, start);
|
|
}
|
|
|
|
function readInt64BE_int64(start) {
|
|
return new Int64BE(this, start);
|
|
}
|
|
|
|
function readFloatBE(start) {
|
|
return ieee754.read(this, start, false, 23, 4);
|
|
}
|
|
|
|
function readDoubleBE(start) {
|
|
return ieee754.read(this, start, false, 52, 8);
|
|
}
|
|
|
|
/***/ }),
|
|
/* 35 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// read-token.js
|
|
|
|
var ReadFormat = __webpack_require__(34);
|
|
|
|
exports.getReadToken = getReadToken;
|
|
|
|
function getReadToken(options) {
|
|
var format = ReadFormat.getReadFormat(options);
|
|
|
|
if (options && options.useraw) {
|
|
return init_useraw(format);
|
|
} else {
|
|
return init_token(format);
|
|
}
|
|
}
|
|
|
|
function init_token(format) {
|
|
var i;
|
|
var token = new Array(256);
|
|
|
|
// positive fixint -- 0x00 - 0x7f
|
|
for (i = 0x00; i <= 0x7f; i++) {
|
|
token[i] = constant(i);
|
|
}
|
|
|
|
// fixmap -- 0x80 - 0x8f
|
|
for (i = 0x80; i <= 0x8f; i++) {
|
|
token[i] = fix(i - 0x80, format.map);
|
|
}
|
|
|
|
// fixarray -- 0x90 - 0x9f
|
|
for (i = 0x90; i <= 0x9f; i++) {
|
|
token[i] = fix(i - 0x90, format.array);
|
|
}
|
|
|
|
// fixstr -- 0xa0 - 0xbf
|
|
for (i = 0xa0; i <= 0xbf; i++) {
|
|
token[i] = fix(i - 0xa0, format.str);
|
|
}
|
|
|
|
// nil -- 0xc0
|
|
token[0xc0] = constant(null);
|
|
|
|
// (never used) -- 0xc1
|
|
token[0xc1] = null;
|
|
|
|
// false -- 0xc2
|
|
// true -- 0xc3
|
|
token[0xc2] = constant(false);
|
|
token[0xc3] = constant(true);
|
|
|
|
// bin 8 -- 0xc4
|
|
// bin 16 -- 0xc5
|
|
// bin 32 -- 0xc6
|
|
token[0xc4] = flex(format.uint8, format.bin);
|
|
token[0xc5] = flex(format.uint16, format.bin);
|
|
token[0xc6] = flex(format.uint32, format.bin);
|
|
|
|
// ext 8 -- 0xc7
|
|
// ext 16 -- 0xc8
|
|
// ext 32 -- 0xc9
|
|
token[0xc7] = flex(format.uint8, format.ext);
|
|
token[0xc8] = flex(format.uint16, format.ext);
|
|
token[0xc9] = flex(format.uint32, format.ext);
|
|
|
|
// float 32 -- 0xca
|
|
// float 64 -- 0xcb
|
|
token[0xca] = format.float32;
|
|
token[0xcb] = format.float64;
|
|
|
|
// uint 8 -- 0xcc
|
|
// uint 16 -- 0xcd
|
|
// uint 32 -- 0xce
|
|
// uint 64 -- 0xcf
|
|
token[0xcc] = format.uint8;
|
|
token[0xcd] = format.uint16;
|
|
token[0xce] = format.uint32;
|
|
token[0xcf] = format.uint64;
|
|
|
|
// int 8 -- 0xd0
|
|
// int 16 -- 0xd1
|
|
// int 32 -- 0xd2
|
|
// int 64 -- 0xd3
|
|
token[0xd0] = format.int8;
|
|
token[0xd1] = format.int16;
|
|
token[0xd2] = format.int32;
|
|
token[0xd3] = format.int64;
|
|
|
|
// fixext 1 -- 0xd4
|
|
// fixext 2 -- 0xd5
|
|
// fixext 4 -- 0xd6
|
|
// fixext 8 -- 0xd7
|
|
// fixext 16 -- 0xd8
|
|
token[0xd4] = fix(1, format.ext);
|
|
token[0xd5] = fix(2, format.ext);
|
|
token[0xd6] = fix(4, format.ext);
|
|
token[0xd7] = fix(8, format.ext);
|
|
token[0xd8] = fix(16, format.ext);
|
|
|
|
// str 8 -- 0xd9
|
|
// str 16 -- 0xda
|
|
// str 32 -- 0xdb
|
|
token[0xd9] = flex(format.uint8, format.str);
|
|
token[0xda] = flex(format.uint16, format.str);
|
|
token[0xdb] = flex(format.uint32, format.str);
|
|
|
|
// array 16 -- 0xdc
|
|
// array 32 -- 0xdd
|
|
token[0xdc] = flex(format.uint16, format.array);
|
|
token[0xdd] = flex(format.uint32, format.array);
|
|
|
|
// map 16 -- 0xde
|
|
// map 32 -- 0xdf
|
|
token[0xde] = flex(format.uint16, format.map);
|
|
token[0xdf] = flex(format.uint32, format.map);
|
|
|
|
// negative fixint -- 0xe0 - 0xff
|
|
for (i = 0xe0; i <= 0xff; i++) {
|
|
token[i] = constant(i - 0x100);
|
|
}
|
|
|
|
return token;
|
|
}
|
|
|
|
function init_useraw(format) {
|
|
var i;
|
|
var token = init_token(format).slice();
|
|
|
|
// raw 8 -- 0xd9
|
|
// raw 16 -- 0xda
|
|
// raw 32 -- 0xdb
|
|
token[0xd9] = token[0xc4];
|
|
token[0xda] = token[0xc5];
|
|
token[0xdb] = token[0xc6];
|
|
|
|
// fixraw -- 0xa0 - 0xbf
|
|
for (i = 0xa0; i <= 0xbf; i++) {
|
|
token[i] = fix(i - 0xa0, format.bin);
|
|
}
|
|
|
|
return token;
|
|
}
|
|
|
|
function constant(value) {
|
|
return function() {
|
|
return value;
|
|
};
|
|
}
|
|
|
|
function flex(lenFunc, decodeFunc) {
|
|
return function(decoder) {
|
|
var len = lenFunc(decoder);
|
|
return decodeFunc(decoder, len);
|
|
};
|
|
}
|
|
|
|
function fix(len, method) {
|
|
return function(decoder) {
|
|
return method(decoder, len);
|
|
};
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 36 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// encoder.js
|
|
|
|
exports.Encoder = Encoder;
|
|
|
|
var EventLite = __webpack_require__(37);
|
|
var EncodeBuffer = __webpack_require__(11).EncodeBuffer;
|
|
|
|
function Encoder(options) {
|
|
if (!(this instanceof Encoder)) return new Encoder(options);
|
|
EncodeBuffer.call(this, options);
|
|
}
|
|
|
|
Encoder.prototype = new EncodeBuffer();
|
|
|
|
EventLite.mixin(Encoder.prototype);
|
|
|
|
Encoder.prototype.encode = function(chunk) {
|
|
this.write(chunk);
|
|
this.emit("data", this.read());
|
|
};
|
|
|
|
Encoder.prototype.end = function(chunk) {
|
|
if (arguments.length) this.encode(chunk);
|
|
this.flush();
|
|
this.emit("end");
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 37 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* event-lite.js - Light-weight EventEmitter (less than 1KB when gzipped)
|
|
*
|
|
* @copyright Yusuke Kawasaki
|
|
* @license MIT
|
|
* @constructor
|
|
* @see https://github.com/kawanet/event-lite
|
|
* @see http://kawanet.github.io/event-lite/EventLite.html
|
|
* @example
|
|
* var EventLite = require("event-lite");
|
|
*
|
|
* function MyClass() {...} // your class
|
|
*
|
|
* EventLite.mixin(MyClass.prototype); // import event methods
|
|
*
|
|
* var obj = new MyClass();
|
|
* obj.on("foo", function() {...}); // add event listener
|
|
* obj.once("bar", function() {...}); // add one-time event listener
|
|
* obj.emit("foo"); // dispatch event
|
|
* obj.emit("bar"); // dispatch another event
|
|
* obj.off("foo"); // remove event listener
|
|
*/
|
|
|
|
function EventLite() {
|
|
if (!(this instanceof EventLite)) return new EventLite();
|
|
}
|
|
|
|
(function(EventLite) {
|
|
// export the class for node.js
|
|
if (true) module.exports = EventLite;
|
|
|
|
// property name to hold listeners
|
|
var LISTENERS = "listeners";
|
|
|
|
// methods to export
|
|
var methods = {
|
|
on: on,
|
|
once: once,
|
|
off: off,
|
|
emit: emit
|
|
};
|
|
|
|
// mixin to self
|
|
mixin(EventLite.prototype);
|
|
|
|
// export mixin function
|
|
EventLite.mixin = mixin;
|
|
|
|
/**
|
|
* Import on(), once(), off() and emit() methods into target object.
|
|
*
|
|
* @function EventLite.mixin
|
|
* @param target {Prototype}
|
|
*/
|
|
|
|
function mixin(target) {
|
|
for (var key in methods) {
|
|
target[key] = methods[key];
|
|
}
|
|
return target;
|
|
}
|
|
|
|
/**
|
|
* Add an event listener.
|
|
*
|
|
* @function EventLite.prototype.on
|
|
* @param type {string}
|
|
* @param func {Function}
|
|
* @returns {EventLite} Self for method chaining
|
|
*/
|
|
|
|
function on(type, func) {
|
|
getListeners(this, type).push(func);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Add one-time event listener.
|
|
*
|
|
* @function EventLite.prototype.once
|
|
* @param type {string}
|
|
* @param func {Function}
|
|
* @returns {EventLite} Self for method chaining
|
|
*/
|
|
|
|
function once(type, func) {
|
|
var that = this;
|
|
wrap.originalListener = func;
|
|
getListeners(that, type).push(wrap);
|
|
return that;
|
|
|
|
function wrap() {
|
|
off.call(that, type, wrap);
|
|
func.apply(this, arguments);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove an event listener.
|
|
*
|
|
* @function EventLite.prototype.off
|
|
* @param [type] {string}
|
|
* @param [func] {Function}
|
|
* @returns {EventLite} Self for method chaining
|
|
*/
|
|
|
|
function off(type, func) {
|
|
var that = this;
|
|
var listners;
|
|
if (!arguments.length) {
|
|
delete that[LISTENERS];
|
|
} else if (!func) {
|
|
listners = that[LISTENERS];
|
|
if (listners) {
|
|
delete listners[type];
|
|
if (!Object.keys(listners).length) return off.call(that);
|
|
}
|
|
} else {
|
|
listners = getListeners(that, type, true);
|
|
if (listners) {
|
|
listners = listners.filter(ne);
|
|
if (!listners.length) return off.call(that, type);
|
|
that[LISTENERS][type] = listners;
|
|
}
|
|
}
|
|
return that;
|
|
|
|
function ne(test) {
|
|
return test !== func && test.originalListener !== func;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Dispatch (trigger) an event.
|
|
*
|
|
* @function EventLite.prototype.emit
|
|
* @param type {string}
|
|
* @param [value] {*}
|
|
* @returns {boolean} True when a listener received the event
|
|
*/
|
|
|
|
function emit(type, value) {
|
|
var that = this;
|
|
var listeners = getListeners(that, type, true);
|
|
if (!listeners) return false;
|
|
var arglen = arguments.length;
|
|
if (arglen === 1) {
|
|
listeners.forEach(zeroarg);
|
|
} else if (arglen === 2) {
|
|
listeners.forEach(onearg);
|
|
} else {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
listeners.forEach(moreargs);
|
|
}
|
|
return !!listeners.length;
|
|
|
|
function zeroarg(func) {
|
|
func.call(that);
|
|
}
|
|
|
|
function onearg(func) {
|
|
func.call(that, value);
|
|
}
|
|
|
|
function moreargs(func) {
|
|
func.apply(that, args);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
|
|
function getListeners(that, type, readonly) {
|
|
if (readonly && !that[LISTENERS]) return;
|
|
var listeners = that[LISTENERS] || (that[LISTENERS] = {});
|
|
return listeners[type] || (listeners[type] = []);
|
|
}
|
|
|
|
})(EventLite);
|
|
|
|
|
|
/***/ }),
|
|
/* 38 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// decoder.js
|
|
|
|
exports.Decoder = Decoder;
|
|
|
|
var EventLite = __webpack_require__(37);
|
|
var DecodeBuffer = __webpack_require__(31).DecodeBuffer;
|
|
|
|
function Decoder(options) {
|
|
if (!(this instanceof Decoder)) return new Decoder(options);
|
|
DecodeBuffer.call(this, options);
|
|
}
|
|
|
|
Decoder.prototype = new DecodeBuffer();
|
|
|
|
EventLite.mixin(Decoder.prototype);
|
|
|
|
Decoder.prototype.decode = function(chunk) {
|
|
if (arguments.length) this.write(chunk);
|
|
this.flush();
|
|
};
|
|
|
|
Decoder.prototype.push = function(chunk) {
|
|
this.emit("data", chunk);
|
|
};
|
|
|
|
Decoder.prototype.end = function(chunk) {
|
|
this.decode(chunk);
|
|
this.emit("end");
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 39 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// encode-stream.js
|
|
|
|
exports.createEncodeStream = EncodeStream;
|
|
|
|
var util = __webpack_require__(40);
|
|
var Transform = __webpack_require__(41).Transform;
|
|
var EncodeBuffer = __webpack_require__(11).EncodeBuffer;
|
|
|
|
util.inherits(EncodeStream, Transform);
|
|
|
|
var DEFAULT_OPTIONS = {objectMode: true};
|
|
|
|
function EncodeStream(options) {
|
|
if (!(this instanceof EncodeStream)) return new EncodeStream(options);
|
|
if (options) {
|
|
options.objectMode = true;
|
|
} else {
|
|
options = DEFAULT_OPTIONS;
|
|
}
|
|
Transform.call(this, options);
|
|
|
|
var stream = this;
|
|
var encoder = this.encoder = new EncodeBuffer(options);
|
|
encoder.push = function(chunk) {
|
|
stream.push(chunk);
|
|
};
|
|
}
|
|
|
|
EncodeStream.prototype._transform = function(chunk, encoding, callback) {
|
|
this.encoder.write(chunk);
|
|
if (callback) callback();
|
|
};
|
|
|
|
EncodeStream.prototype._flush = function(callback) {
|
|
this.encoder.flush();
|
|
if (callback) callback();
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 40 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("util");
|
|
|
|
/***/ }),
|
|
/* 41 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("stream");
|
|
|
|
/***/ }),
|
|
/* 42 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// decode-stream.js
|
|
|
|
exports.createDecodeStream = DecodeStream;
|
|
|
|
var util = __webpack_require__(40);
|
|
var Transform = __webpack_require__(41).Transform;
|
|
var DecodeBuffer = __webpack_require__(31).DecodeBuffer;
|
|
|
|
util.inherits(DecodeStream, Transform);
|
|
|
|
var DEFAULT_OPTIONS = {objectMode: true};
|
|
|
|
function DecodeStream(options) {
|
|
if (!(this instanceof DecodeStream)) return new DecodeStream(options);
|
|
if (options) {
|
|
options.objectMode = true;
|
|
} else {
|
|
options = DEFAULT_OPTIONS;
|
|
}
|
|
Transform.call(this, options);
|
|
var stream = this;
|
|
var decoder = this.decoder = new DecodeBuffer(options);
|
|
decoder.push = function(chunk) {
|
|
stream.push(chunk);
|
|
};
|
|
}
|
|
|
|
DecodeStream.prototype._transform = function(chunk, encoding, callback) {
|
|
this.decoder.write(chunk);
|
|
this.decoder.flush();
|
|
if (callback) callback();
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 43 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// ext.js
|
|
|
|
// load both interfaces
|
|
__webpack_require__(32);
|
|
__webpack_require__(12);
|
|
|
|
exports.createCodec = __webpack_require__(28).createCodec;
|
|
|
|
|
|
/***/ }),
|
|
/* 44 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// codec.js
|
|
|
|
// load both interfaces
|
|
__webpack_require__(32);
|
|
__webpack_require__(12);
|
|
|
|
// @public
|
|
// msgpack.codec.preset
|
|
|
|
exports.codec = {
|
|
preset: __webpack_require__(28).preset
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 45 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const stream_1 = __webpack_require__(41);
|
|
class Buffered extends stream_1.Transform {
|
|
constructor() {
|
|
super({
|
|
readableHighWaterMark: 10 * 1024 * 1024,
|
|
writableHighWaterMark: 10 * 1024 * 1024,
|
|
});
|
|
this.chunks = null;
|
|
this.timer = null;
|
|
}
|
|
sendData() {
|
|
const { chunks } = this;
|
|
if (chunks) {
|
|
this.chunks = null;
|
|
const buf = Buffer.concat(chunks);
|
|
this.push(buf);
|
|
}
|
|
}
|
|
// eslint-disable-next-line consistent-return
|
|
_transform(chunk, _encoding, callback) {
|
|
const { chunks, timer } = this;
|
|
const MIN_SIZE = Buffer.poolSize;
|
|
if (timer)
|
|
clearTimeout(timer);
|
|
if (chunk.length < MIN_SIZE) {
|
|
if (!chunks)
|
|
return callback(null, chunk);
|
|
chunks.push(chunk);
|
|
this.sendData();
|
|
callback();
|
|
}
|
|
else {
|
|
if (!chunks) {
|
|
this.chunks = [chunk];
|
|
}
|
|
else {
|
|
chunks.push(chunk);
|
|
}
|
|
this.timer = setTimeout(this.sendData.bind(this), 20);
|
|
callback();
|
|
}
|
|
}
|
|
_flush(callback) {
|
|
const { chunks } = this;
|
|
if (chunks) {
|
|
this.chunks = null;
|
|
const buf = Buffer.concat(chunks);
|
|
callback(null, buf);
|
|
}
|
|
else {
|
|
callback();
|
|
}
|
|
}
|
|
}
|
|
exports.default = Buffered;
|
|
|
|
|
|
/***/ }),
|
|
/* 46 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const Buffer_1 = __webpack_require__(47);
|
|
const Window_1 = __webpack_require__(50);
|
|
const Tabpage_1 = __webpack_require__(52);
|
|
var ExtType;
|
|
(function (ExtType) {
|
|
ExtType[ExtType["Buffer"] = 0] = "Buffer";
|
|
ExtType[ExtType["Window"] = 1] = "Window";
|
|
ExtType[ExtType["Tabpage"] = 2] = "Tabpage";
|
|
})(ExtType = exports.ExtType || (exports.ExtType = {}));
|
|
exports.Metadata = [
|
|
{
|
|
constructor: Buffer_1.Buffer,
|
|
name: 'Buffer',
|
|
prefix: 'nvim_buf_',
|
|
},
|
|
{
|
|
constructor: Window_1.Window,
|
|
name: 'Window',
|
|
prefix: 'nvim_win_',
|
|
},
|
|
{
|
|
constructor: Tabpage_1.Tabpage,
|
|
name: 'Tabpage',
|
|
prefix: 'nvim_tabpage_',
|
|
},
|
|
];
|
|
|
|
|
|
/***/ }),
|
|
/* 47 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const Base_1 = __webpack_require__(48);
|
|
const client_1 = __webpack_require__(7);
|
|
class Buffer extends Base_1.BaseApi {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.prefix = 'nvim_buf_';
|
|
}
|
|
get isAttached() {
|
|
return this.client.isAttached(this.id);
|
|
}
|
|
/**
|
|
* Attach to buffer to listen to buffer events
|
|
* @param sendBuffer Set to true if the initial notification should contain
|
|
* the whole buffer. If so, the first notification will be a
|
|
* `nvim_buf_lines_event`. Otherwise, the first notification will be
|
|
* a `nvim_buf_changedtick_event`
|
|
*/
|
|
attach(sendBuffer = false, options = {}) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (this.isAttached)
|
|
return true;
|
|
let res = false;
|
|
try {
|
|
res = yield this.request(`${this.prefix}attach`, [sendBuffer, options]);
|
|
}
|
|
catch (e) {
|
|
res = false;
|
|
}
|
|
if (res) {
|
|
this.client[client_1.ATTACH_BUFFER](this);
|
|
}
|
|
return this.isAttached;
|
|
});
|
|
}
|
|
/**
|
|
* Detach from buffer to stop listening to buffer events
|
|
*/
|
|
detach() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
this.client[client_1.DETACH_BUFFER](this);
|
|
try {
|
|
yield this.request(`${this.prefix}detach`, []);
|
|
}
|
|
catch (e) {
|
|
// noop
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* Get the bufnr of Buffer
|
|
*/
|
|
get id() {
|
|
return this.data;
|
|
}
|
|
/** Total number of lines in buffer */
|
|
get length() {
|
|
return this.request(`${this.prefix}line_count`, []);
|
|
}
|
|
/** Get lines in buffer */
|
|
get lines() {
|
|
return this.getLines();
|
|
}
|
|
/** Gets a changed tick of a buffer */
|
|
get changedtick() {
|
|
return this.request(`${this.prefix}get_changedtick`, []);
|
|
}
|
|
get commands() {
|
|
return this.getCommands();
|
|
}
|
|
getCommands(options = {}) {
|
|
return this.request(`${this.prefix}get_commands`, [options]);
|
|
}
|
|
/** Get specific lines of buffer */
|
|
getLines({ start, end, strictIndexing } = { start: 0, end: -1, strictIndexing: true }) {
|
|
const indexing = typeof strictIndexing === 'undefined' ? true : strictIndexing;
|
|
return this.request(`${this.prefix}get_lines`, [
|
|
start,
|
|
end,
|
|
indexing,
|
|
]);
|
|
}
|
|
/** Set lines of buffer given indeces */
|
|
setLines(_lines, { start: _start, end: _end, strictIndexing } = {
|
|
strictIndexing: true,
|
|
}, notify = false) {
|
|
// TODO: Error checking
|
|
// if (typeof start === 'undefined' || typeof end === 'undefined') {
|
|
// }
|
|
const indexing = typeof strictIndexing === 'undefined' ? true : strictIndexing;
|
|
const lines = typeof _lines === 'string' ? [_lines] : _lines;
|
|
const end = typeof _end !== 'undefined' ? _end : _start + 1;
|
|
const method = notify ? 'notify' : 'request';
|
|
return this[method](`${this.prefix}set_lines`, [
|
|
_start,
|
|
end,
|
|
indexing,
|
|
lines,
|
|
]);
|
|
}
|
|
/**
|
|
* Set virtual text for a line
|
|
*
|
|
* @public
|
|
* @param {number} src_id - Source group to use or 0 to use a new group, or -1
|
|
* @param {number} line - Line to annotate with virtual text (zero-indexed)
|
|
* @param {Chunk[]} chunks - List with [text, hl_group]
|
|
* @param {{[index} opts
|
|
* @returns {Promise<number>}
|
|
*/
|
|
setVirtualText(src_id, line, chunks, opts = {}) {
|
|
this.notify(`${this.prefix}set_virtual_text`, [
|
|
src_id,
|
|
line,
|
|
chunks,
|
|
opts,
|
|
]);
|
|
return Promise.resolve(src_id);
|
|
}
|
|
/** Insert lines at `start` index */
|
|
insert(lines, start) {
|
|
return this.setLines(lines, {
|
|
start,
|
|
end: start,
|
|
strictIndexing: true,
|
|
});
|
|
}
|
|
/** Replace lines starting at `start` index */
|
|
replace(_lines, start) {
|
|
const lines = typeof _lines === 'string' ? [_lines] : _lines;
|
|
return this.setLines(lines, {
|
|
start,
|
|
end: start + lines.length,
|
|
strictIndexing: false,
|
|
});
|
|
}
|
|
/** Remove lines at index */
|
|
remove(start, end, strictIndexing = false) {
|
|
return this.setLines([], { start, end, strictIndexing });
|
|
}
|
|
/** Append a string or list of lines to end of buffer */
|
|
append(lines) {
|
|
return this.setLines(lines, {
|
|
start: -1,
|
|
end: -1,
|
|
strictIndexing: false,
|
|
});
|
|
}
|
|
/** Get buffer name */
|
|
get name() {
|
|
return this.request(`${this.prefix}get_name`, []);
|
|
}
|
|
/** Set current buffer name */
|
|
setName(value) {
|
|
return this.request(`${this.prefix}set_name`, [value]);
|
|
}
|
|
/** Is current buffer valid */
|
|
get valid() {
|
|
return this.request(`${this.prefix}is_valid`, []);
|
|
}
|
|
/** Get mark position given mark name */
|
|
mark(name) {
|
|
return this.request(`${this.prefix}get_mark`, [name]);
|
|
}
|
|
// range(start, end) {
|
|
// """Return a `Range` object, which represents part of the Buffer."""
|
|
// return Range(this, start, end)
|
|
// }
|
|
/** Gets keymap */
|
|
getKeymap(mode) {
|
|
return this.request(`${this.prefix}get_keymap`, [mode]);
|
|
}
|
|
/**
|
|
* Checks if a buffer is valid and loaded. See |api-buffer| for
|
|
* more info about unloaded buffers.
|
|
*/
|
|
get loaded() {
|
|
return this.request(`${this.prefix}is_loaded`, []);
|
|
}
|
|
/**
|
|
* Returns the byte offset for a line.
|
|
*
|
|
* Line 1 (index=0) has offset 0. UTF-8 bytes are counted. EOL is
|
|
* one byte. 'fileformat' and 'fileencoding' are ignored. The
|
|
* line index just after the last line gives the total byte-count
|
|
* of the buffer. A final EOL byte is counted if it would be
|
|
* written, see 'eol'.
|
|
*
|
|
* Unlike |line2byte()|, throws error for out-of-bounds indexing.
|
|
* Returns -1 for unloaded buffer.
|
|
*
|
|
* @return {Number} Integer byte offset, or -1 for unloaded buffer.
|
|
*/
|
|
getOffset(index) {
|
|
return this.request(`${this.prefix}get_offset`, [index]);
|
|
}
|
|
/**
|
|
Adds a highlight to buffer.
|
|
|
|
This can be used for plugins which dynamically generate
|
|
highlights to a buffer (like a semantic highlighter or
|
|
linter). The function adds a single highlight to a buffer.
|
|
Unlike matchaddpos() highlights follow changes to line
|
|
numbering (as lines are inserted/removed above the highlighted
|
|
line), like signs and marks do.
|
|
|
|
"src_id" is useful for batch deletion/updating of a set of
|
|
highlights. When called with src_id = 0, an unique source id
|
|
is generated and returned. Succesive calls can pass in it as
|
|
"src_id" to add new highlights to the same source group. All
|
|
highlights in the same group can then be cleared with
|
|
nvim_buf_clear_highlight. If the highlight never will be
|
|
manually deleted pass in -1 for "src_id".
|
|
|
|
If "hl_group" is the empty string no highlight is added, but a
|
|
new src_id is still returned. This is useful for an external
|
|
plugin to synchrounously request an unique src_id at
|
|
initialization, and later asynchronously add and clear
|
|
highlights in response to buffer changes. */
|
|
addHighlight({ hlGroup: _hlGroup, line, colStart: _start, colEnd: _end, srcId: _srcId, }) {
|
|
const hlGroup = typeof _hlGroup !== 'undefined' ? _hlGroup : '';
|
|
const colEnd = typeof _end !== 'undefined' ? _end : -1;
|
|
const colStart = typeof _start !== 'undefined' ? _start : -0;
|
|
const srcId = typeof _srcId !== 'undefined' ? _srcId : -1;
|
|
const method = hlGroup === '' ? 'request' : 'notify';
|
|
let res = this[method](`${this.prefix}add_highlight`, [
|
|
srcId,
|
|
hlGroup,
|
|
line,
|
|
colStart,
|
|
colEnd,
|
|
]);
|
|
return method === 'request' ? res : Promise.resolve(null);
|
|
}
|
|
/** Clears highlights from a given source group and a range of
|
|
lines
|
|
To clear a source group in the entire buffer, pass in 1 and -1
|
|
to lineStart and lineEnd respectively. */
|
|
clearHighlight(args = {}) {
|
|
const defaults = {
|
|
srcId: -1,
|
|
lineStart: 0,
|
|
lineEnd: -1,
|
|
};
|
|
const { srcId, lineStart, lineEnd } = Object.assign({}, defaults, args);
|
|
return this.notify(`${this.prefix}clear_highlight`, [
|
|
srcId,
|
|
lineStart,
|
|
lineEnd,
|
|
]);
|
|
}
|
|
clearNamespace(id, lineStart = 0, lineEnd = -1) {
|
|
return this.notify(`${this.prefix}clear_namespace`, [
|
|
id,
|
|
lineStart,
|
|
lineEnd,
|
|
]);
|
|
}
|
|
/**
|
|
* Listens to buffer for events
|
|
*/
|
|
listen(eventName, cb) {
|
|
if (!this.isAttached) {
|
|
throw new Error('buffer not attached');
|
|
}
|
|
this.client.attachBufferEvent(this, eventName, cb);
|
|
return () => {
|
|
this.unlisten(eventName, cb);
|
|
};
|
|
}
|
|
unlisten(eventName, cb) {
|
|
this.client.detachBufferEvent(this, eventName, cb);
|
|
}
|
|
}
|
|
exports.Buffer = Buffer;
|
|
|
|
|
|
/***/ }),
|
|
/* 48 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const events_1 = __webpack_require__(49);
|
|
const isVim = process.env.VIM_NODE_RPC == '1';
|
|
// i.e. a plugin that detaches will affect all plugins registered on host
|
|
// const EXCLUDED = ['nvim_buf_attach', 'nvim_buf_detach']
|
|
// Instead of dealing with multiple inheritance (or lackof), just extend EE
|
|
// Only the Neovim API class should use EE though
|
|
class BaseApi extends events_1.EventEmitter {
|
|
constructor({ transport, data, client, }) {
|
|
super();
|
|
this.setTransport(transport);
|
|
this.data = data;
|
|
this.client = client;
|
|
}
|
|
setTransport(transport) {
|
|
this.transport = transport;
|
|
}
|
|
equals(other) {
|
|
try {
|
|
return String(this.data) === String(other.data);
|
|
}
|
|
catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
request(name, args = []) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
return new Promise((resolve, reject) => {
|
|
this.transport.request(name, this.getArgsByPrefix(args), (err, res) => {
|
|
if (err) {
|
|
reject(new Error(`request error ${name} - ${err[1]}`));
|
|
}
|
|
else {
|
|
resolve(res);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
getArgsByPrefix(args) {
|
|
// Check if class is Neovim and if so, should not send `this` as first arg
|
|
if (this.prefix !== 'nvim_' && args[0] != this) {
|
|
let id = isVim ? this.data : this;
|
|
return [id, ...args];
|
|
}
|
|
return args;
|
|
}
|
|
/** Retrieves a scoped variable depending on type (using `this.prefix`) */
|
|
getVar(name) {
|
|
return this.request(`${this.prefix}get_var`, [name]).then(res => res, _err => {
|
|
return null;
|
|
});
|
|
}
|
|
setVar(name, value, isNotify = false) {
|
|
if (isNotify) {
|
|
this.notify(`${this.prefix}set_var`, [name, value]);
|
|
return;
|
|
}
|
|
return this.request(`${this.prefix}set_var`, [name, value]);
|
|
}
|
|
/** Delete a scoped variable */
|
|
deleteVar(name) {
|
|
this.notify(`${this.prefix}del_var`, [name]);
|
|
}
|
|
/** Retrieves a scoped option depending on type of `this` */
|
|
getOption(name) {
|
|
return this.request(`${this.prefix}get_option`, [name]);
|
|
}
|
|
setOption(name, value, isNotify) {
|
|
if (isNotify) {
|
|
this.notify(`${this.prefix}set_option`, [name, value]);
|
|
return;
|
|
}
|
|
return this.request(`${this.prefix}set_option`, [name, value]);
|
|
}
|
|
/** `request` is basically the same except you can choose to wait forpromise to be resolved */
|
|
notify(name, args = []) {
|
|
this.transport.notify(name, this.getArgsByPrefix(args));
|
|
}
|
|
}
|
|
exports.BaseApi = BaseApi;
|
|
|
|
|
|
/***/ }),
|
|
/* 49 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("events");
|
|
|
|
/***/ }),
|
|
/* 50 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const Base_1 = __webpack_require__(48);
|
|
const timers_1 = __webpack_require__(51);
|
|
class Window extends Base_1.BaseApi {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.prefix = 'nvim_win_';
|
|
}
|
|
/**
|
|
* The windowid that not change within a Vim session
|
|
*/
|
|
get id() {
|
|
return this.data;
|
|
}
|
|
/** Get current buffer of window */
|
|
get buffer() {
|
|
return this.request(`${this.prefix}get_buf`, []);
|
|
}
|
|
/** Get the Tabpage that contains the window */
|
|
get tabpage() {
|
|
return this.request(`${this.prefix}get_tabpage`, []);
|
|
}
|
|
/** Get cursor position */
|
|
get cursor() {
|
|
return this.request(`${this.prefix}get_cursor`, []);
|
|
}
|
|
setCursor(pos, isNotify = false) {
|
|
let method = isNotify ? 'notify' : 'request';
|
|
return this[method](`${this.prefix}set_cursor`, [pos]);
|
|
}
|
|
/** Get window height by number of rows */
|
|
get height() {
|
|
return this.request(`${this.prefix}get_height`, []);
|
|
}
|
|
setHeight(height, isNotify = false) {
|
|
let method = isNotify ? 'notify' : 'request';
|
|
return this[method](`${this.prefix}set_height`, [height]);
|
|
}
|
|
/** Get window width by number of columns */
|
|
get width() {
|
|
return this.request(`${this.prefix}get_width`, []);
|
|
}
|
|
setWidth(width, isNotify = false) {
|
|
let method = isNotify ? 'notify' : 'request';
|
|
return this[method](`${this.prefix}set_height`, [width]);
|
|
}
|
|
/** Get window position */
|
|
get position() {
|
|
return this.request(`${this.prefix}get_position`, []);
|
|
}
|
|
/** 0-indexed, on-screen window position(row) in display cells. */
|
|
get row() {
|
|
return this.request(`${this.prefix}get_position`, []).then(position => position[0]);
|
|
}
|
|
/** 0-indexed, on-screen window position(col) in display cells. */
|
|
get col() {
|
|
return this.request(`${this.prefix}get_position`, []).then(position => position[1]);
|
|
}
|
|
/** Is window valid */
|
|
get valid() {
|
|
return this.request(`${this.prefix}is_valid`, []);
|
|
}
|
|
/** Get window number */
|
|
get number() {
|
|
return this.request(`${this.prefix}get_number`, []);
|
|
}
|
|
setConfig(options, isNotify) {
|
|
let method = isNotify ? 'notify' : 'request';
|
|
return this[method](`${this.prefix}set_config`, [options]);
|
|
}
|
|
getConfig() {
|
|
return this.request(`${this.prefix}get_config`, []);
|
|
}
|
|
close(force, isNotify) {
|
|
if (isNotify) {
|
|
this.notify(`${this.prefix}close`, [force]);
|
|
let count = 0;
|
|
let interval = setInterval(() => {
|
|
if (count == 5)
|
|
return timers_1.clearInterval(interval);
|
|
this.request(`${this.prefix}is_valid`, []).then(valid => {
|
|
if (!valid) {
|
|
timers_1.clearInterval(interval);
|
|
}
|
|
else {
|
|
this.notify(`${this.prefix}close`, [force]);
|
|
}
|
|
}, () => {
|
|
timers_1.clearInterval(interval);
|
|
});
|
|
count++;
|
|
}, 50);
|
|
return null;
|
|
}
|
|
return this.request(`${this.prefix}close`, [force]);
|
|
}
|
|
}
|
|
exports.Window = Window;
|
|
|
|
|
|
/***/ }),
|
|
/* 51 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("timers");
|
|
|
|
/***/ }),
|
|
/* 52 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const Base_1 = __webpack_require__(48);
|
|
class Tabpage extends Base_1.BaseApi {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.prefix = 'nvim_tabpage_';
|
|
}
|
|
/** Returns all windows of tabpage */
|
|
get windows() {
|
|
return this.request(`${this.prefix}list_wins`, []);
|
|
}
|
|
/** Gets the current window of tabpage */
|
|
get window() {
|
|
return this.request(`${this.prefix}get_win`, []);
|
|
}
|
|
/** Is current tabpage valid */
|
|
get valid() {
|
|
return this.request(`${this.prefix}is_valid`, []);
|
|
}
|
|
/** Tabpage number */
|
|
get number() {
|
|
return this.request(`${this.prefix}get_number`, []);
|
|
}
|
|
/** Invalid */
|
|
getOption() {
|
|
throw new Error('Tabpage does not have `getOption`');
|
|
}
|
|
/** Invalid */
|
|
setOption() {
|
|
throw new Error('Tabpage does not have `setOption`');
|
|
}
|
|
}
|
|
exports.Tabpage = Tabpage;
|
|
|
|
|
|
/***/ }),
|
|
/* 53 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const events_1 = __webpack_require__(49);
|
|
const logger_1 = __webpack_require__(54);
|
|
const debug = process.env.NODE_CLIENT_LOG_LEVEL == 'debug';
|
|
const logger = logger_1.createLogger('transport');
|
|
class Transport extends events_1.EventEmitter {
|
|
constructor() {
|
|
super(...arguments);
|
|
this._paused = false;
|
|
this.paused = [];
|
|
}
|
|
debug(key, ...meta) {
|
|
if (!debug)
|
|
return;
|
|
logger.debug(key, ...meta);
|
|
}
|
|
debugMessage(msg) {
|
|
if (!debug)
|
|
return;
|
|
const msgType = msg[0];
|
|
if (msgType == 0) {
|
|
logger.debug('receive request:', msg.slice(1));
|
|
}
|
|
else if (msgType == 1) {
|
|
logger.debug('receive response:', msg.slice(1));
|
|
}
|
|
else if (msgType == 2) {
|
|
logger.debug('receive notification:', msg.slice(1));
|
|
}
|
|
else {
|
|
logger.debug('unknown message:', msg);
|
|
}
|
|
}
|
|
pauseNotification() {
|
|
this._paused = true;
|
|
}
|
|
resumeNotification(isNotify = false) {
|
|
this._paused = false;
|
|
let list = this.paused;
|
|
if (list.length) {
|
|
this.paused = [];
|
|
return new Promise((resolve, reject) => {
|
|
if (!isNotify)
|
|
return this.request('nvim_call_atomic', [list], (err, res) => {
|
|
if (err)
|
|
return reject(new Error(`call_atomic error: ${err[1]}`));
|
|
resolve(res);
|
|
});
|
|
this.notify('nvim_call_atomic', [list]);
|
|
resolve();
|
|
});
|
|
}
|
|
return isNotify ? null : Promise.resolve();
|
|
}
|
|
}
|
|
exports.default = Transport;
|
|
|
|
|
|
/***/ }),
|
|
/* 54 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const fs_1 = __importDefault(__webpack_require__(55));
|
|
const os_1 = __importDefault(__webpack_require__(56));
|
|
const path_1 = __importDefault(__webpack_require__(57));
|
|
function getLogFile() {
|
|
let file = process.env.NODE_CLIENT_LOG_FILE;
|
|
if (file)
|
|
return file;
|
|
let dir = process.env.XDG_RUNTIME_DIR;
|
|
if (dir)
|
|
return path_1.default.join(dir, 'node-client.log');
|
|
return path_1.default.join(os_1.default.tmpdir(), `node-client-${process.pid}.log`);
|
|
}
|
|
const LOG_FILE_PATH = getLogFile();
|
|
const level = process.env.NODE_CLIENT_LOG_LEVEL || 'info';
|
|
let invalid = process.getuid && process.getuid() == 0;
|
|
if (!invalid) {
|
|
try {
|
|
fs_1.default.mkdirSync(path_1.default.dirname(LOG_FILE_PATH), { recursive: true });
|
|
fs_1.default.writeFileSync(LOG_FILE_PATH, '', { encoding: 'utf8', mode: 0o666 });
|
|
}
|
|
catch (_e) {
|
|
invalid = true;
|
|
}
|
|
}
|
|
function toObject(arg) {
|
|
if (arg == null) {
|
|
return arg;
|
|
}
|
|
if (Array.isArray(arg)) {
|
|
return arg.map(o => toObject(o));
|
|
}
|
|
if (typeof arg == 'object' && typeof arg.prefix == 'string' && typeof arg.data == 'number') {
|
|
return '[' + arg.prefix + arg.data + ']';
|
|
}
|
|
return arg;
|
|
}
|
|
function toString(arg) {
|
|
if (arg == null)
|
|
return String(arg);
|
|
if (typeof arg == 'object')
|
|
return JSON.stringify(arg, null, 2);
|
|
return String(arg);
|
|
}
|
|
const stream = invalid ? null : fs_1.default.createWriteStream(LOG_FILE_PATH, { encoding: 'utf8' });
|
|
class Logger {
|
|
constructor(name) {
|
|
this.name = name;
|
|
}
|
|
getText(level, data, meta) {
|
|
let more = '';
|
|
if (meta.length) {
|
|
let arr = toObject(meta);
|
|
more = ' ' + arr.map(o => toString(o));
|
|
}
|
|
return `${new Date().toLocaleTimeString()} ${level.toUpperCase()} [${this.name}] - ${data}${more}\n`;
|
|
}
|
|
debug(data, ...meta) {
|
|
if (level != 'debug' || stream == null)
|
|
return;
|
|
stream.write(this.getText('debug', data, meta));
|
|
}
|
|
info(data, ...meta) {
|
|
if (stream == null)
|
|
return;
|
|
stream.write(this.getText('info', data, meta));
|
|
}
|
|
error(data, ...meta) {
|
|
if (stream == null)
|
|
return;
|
|
stream.write(this.getText('error', data, meta));
|
|
}
|
|
trace(data, ...meta) {
|
|
if (level != 'trace' || stream == null)
|
|
return;
|
|
stream.write(this.getText('trace', data, meta));
|
|
}
|
|
}
|
|
function createLogger(name) {
|
|
return new Logger(name);
|
|
}
|
|
exports.createLogger = createLogger;
|
|
|
|
|
|
/***/ }),
|
|
/* 55 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("fs");
|
|
|
|
/***/ }),
|
|
/* 56 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("os");
|
|
|
|
/***/ }),
|
|
/* 57 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("path");
|
|
|
|
/***/ }),
|
|
/* 58 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const base_1 = __importDefault(__webpack_require__(53));
|
|
const connection_1 = __importDefault(__webpack_require__(59));
|
|
const request_1 = __importDefault(__webpack_require__(61));
|
|
class VimTransport extends base_1.default {
|
|
constructor() {
|
|
super();
|
|
this.pending = new Map();
|
|
this.nextRequestId = 0;
|
|
this.attached = false;
|
|
this.notifyMethod = process.env.COC_NVIM == '1' ? 'coc#api#notify' : 'nvim#api#notify';
|
|
}
|
|
attach(writer, reader, client) {
|
|
let connection = this.connection = new connection_1.default(reader, writer);
|
|
this.attached = true;
|
|
this.client = client;
|
|
connection.on('request', (id, obj) => {
|
|
let [method, args] = obj;
|
|
this.emit('request', method, args, this.createResponse(id));
|
|
});
|
|
connection.on('notification', (obj) => {
|
|
let [event, args] = obj;
|
|
this.emit('notification', event.toString(), args);
|
|
});
|
|
connection.on('response', (id, obj) => {
|
|
let req = this.pending.get(id);
|
|
if (req) {
|
|
this.pending.delete(id);
|
|
let err = null;
|
|
let result = null;
|
|
if (!Array.isArray(obj)) {
|
|
err = obj;
|
|
}
|
|
else {
|
|
err = obj[0];
|
|
result = obj[1];
|
|
}
|
|
req.callback(this.client, err, result);
|
|
}
|
|
});
|
|
}
|
|
detach() {
|
|
if (!this.attached)
|
|
return;
|
|
this.attached = false;
|
|
this.connection.dispose();
|
|
}
|
|
/**
|
|
* Send request to vim
|
|
*/
|
|
request(method, args, cb) {
|
|
if (!this.attached)
|
|
return cb([0, 'transport disconnected']);
|
|
if (!this.client.hasFunction(method)) {
|
|
// tslint:disable-next-line: no-console
|
|
console.error(`method: ${method} not supported.`);
|
|
}
|
|
this.nextRequestId = this.nextRequestId - 1;
|
|
let req = new request_1.default(this.connection, cb, this.nextRequestId);
|
|
this.pending.set(this.nextRequestId, req);
|
|
req.request(method, args);
|
|
}
|
|
notify(method, args) {
|
|
if (!this.attached)
|
|
return;
|
|
if (!this.client.hasFunction(method)) {
|
|
// tslint:disable-next-line: no-console
|
|
console.error(`method: ${method} not supported.`);
|
|
}
|
|
if (this._paused) {
|
|
this.paused.push([method, args]);
|
|
return;
|
|
}
|
|
this.connection.call(this.notifyMethod, [method.slice(5), args]);
|
|
}
|
|
createResponse(requestId) {
|
|
let called = false;
|
|
let { connection } = this;
|
|
return {
|
|
send: (resp, isError) => {
|
|
if (called || !this.attached)
|
|
return;
|
|
called = true;
|
|
let err = null;
|
|
if (isError)
|
|
err = typeof resp === 'string' ? resp : resp.toString();
|
|
connection.response(requestId, [err, isError ? null : resp]);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
exports.VimTransport = VimTransport;
|
|
|
|
|
|
/***/ }),
|
|
/* 59 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const events_1 = __importDefault(__webpack_require__(49));
|
|
const readline_1 = __importDefault(__webpack_require__(60));
|
|
const logger_1 = __webpack_require__(54);
|
|
const logger = logger_1.createLogger('connection');
|
|
const debug = process.env.NODE_CLIENT_LOG_LEVEL == 'debug';
|
|
class Connection extends events_1.default {
|
|
constructor(readable, writeable) {
|
|
super();
|
|
this.readable = readable;
|
|
this.writeable = writeable;
|
|
const rl = readline_1.default.createInterface(this.readable);
|
|
rl.on('line', (line) => {
|
|
this.parseData(line);
|
|
});
|
|
rl.on('close', () => {
|
|
logger.error('connection closed');
|
|
process.exit(0);
|
|
});
|
|
}
|
|
parseData(str) {
|
|
if (str.length == 0)
|
|
return;
|
|
let arr;
|
|
try {
|
|
arr = JSON.parse(str);
|
|
}
|
|
catch (e) {
|
|
// tslint:disable-next-line: no-console
|
|
console.error(`Invalid data from vim: ${str}`);
|
|
return;
|
|
}
|
|
// request, notification, response
|
|
let [id, obj] = arr;
|
|
logger.debug('received:', arr);
|
|
if (id > 0) {
|
|
this.emit('request', id, obj);
|
|
}
|
|
else if (id == 0) {
|
|
this.emit('notification', obj);
|
|
}
|
|
else {
|
|
// response for previous request
|
|
this.emit('response', id, obj);
|
|
}
|
|
}
|
|
response(requestId, data) {
|
|
this.send([requestId, data || null]);
|
|
}
|
|
notify(event, data) {
|
|
this.send([0, [event, data || null]]);
|
|
}
|
|
send(arr) {
|
|
if (debug)
|
|
logger.debug('send:', arr[0], arr.slice(1));
|
|
try {
|
|
this.writeable.write(JSON.stringify(arr) + '\n');
|
|
}
|
|
catch (e) {
|
|
logger.error('Send error:', arr);
|
|
}
|
|
}
|
|
redraw(force = false) {
|
|
this.send(['redraw', force ? 'force' : '']);
|
|
}
|
|
commmand(cmd) {
|
|
this.send(['ex', cmd]);
|
|
}
|
|
expr(expr) {
|
|
this.send(['expr', expr]);
|
|
}
|
|
call(func, args, requestId) {
|
|
if (!requestId) {
|
|
this.send(['call', func, args]);
|
|
return;
|
|
}
|
|
this.send(['call', func, args, requestId]);
|
|
}
|
|
dispose() {
|
|
this.removeAllListeners();
|
|
}
|
|
}
|
|
exports.default = Connection;
|
|
|
|
|
|
/***/ }),
|
|
/* 60 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("readline");
|
|
|
|
/***/ }),
|
|
/* 61 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const logger_1 = __webpack_require__(54);
|
|
const logger = logger_1.createLogger('request');
|
|
const debug = process.env.NODE_CLIENT_LOG_LEVEL == 'debug';
|
|
const func = process.env.COC_NVIM == '1' ? 'coc#api#call' : 'nvim#api#call';
|
|
class Request {
|
|
constructor(connection, cb, id) {
|
|
this.connection = connection;
|
|
this.cb = cb;
|
|
this.id = id;
|
|
}
|
|
request(method, args = []) {
|
|
this.method = method;
|
|
this.args = args;
|
|
this.connection.call(func, [method.slice(5), args], this.id);
|
|
}
|
|
callback(client, err, result) {
|
|
let { method, cb } = this;
|
|
if (debug && err) {
|
|
logger.debug(`request ${this.method} error:`, err, this.args);
|
|
}
|
|
if (err)
|
|
return cb([0, err.toString()]);
|
|
switch (method) {
|
|
case 'nvim_list_wins':
|
|
case 'nvim_tabpage_list_wins':
|
|
return cb(null, result.map(o => client.createWindow(o)));
|
|
case 'nvim_tabpage_get_win':
|
|
case 'nvim_get_current_win':
|
|
case 'nvim_open_win':
|
|
return cb(null, client.createWindow(result));
|
|
case 'nvim_list_bufs':
|
|
return cb(null, result.map(o => client.createBuffer(o)));
|
|
case 'nvim_win_get_buf':
|
|
case 'nvim_create_buf':
|
|
case 'nvim_get_current_buf':
|
|
return cb(null, client.createBuffer(result));
|
|
case 'nvim_list_tabpages':
|
|
return cb(null, result.map(o => client.createTabpage(o)));
|
|
case 'nvim_get_current_tabpage':
|
|
return cb(null, client.createTabpage(result));
|
|
default:
|
|
return cb(null, result);
|
|
}
|
|
}
|
|
}
|
|
exports.default = Request;
|
|
|
|
|
|
/***/ }),
|
|
/* 62 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const Base_1 = __webpack_require__(48);
|
|
const Buffer_1 = __webpack_require__(47);
|
|
const Tabpage_1 = __webpack_require__(52);
|
|
const Window_1 = __webpack_require__(50);
|
|
const isVim = process.env.VIM_NODE_RPC == '1';
|
|
/**
|
|
* Neovim API
|
|
*/
|
|
class Neovim extends Base_1.BaseApi {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.prefix = 'nvim_';
|
|
this.Buffer = Buffer_1.Buffer;
|
|
this.Window = Window_1.Window;
|
|
this.Tabpage = Tabpage_1.Tabpage;
|
|
}
|
|
getArgs(args) {
|
|
if (!args)
|
|
return [];
|
|
if (Array.isArray(args))
|
|
return args;
|
|
return [args];
|
|
}
|
|
get apiInfo() {
|
|
return this.request(`${this.prefix}get_api_info`);
|
|
}
|
|
/** Get list of all buffers */
|
|
get buffers() {
|
|
return this.request(`${this.prefix}list_bufs`);
|
|
}
|
|
/** Get current buffer */
|
|
get buffer() {
|
|
return this.request(`${this.prefix}get_current_buf`);
|
|
}
|
|
/** Set current buffer */
|
|
setBuffer(buffer) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
yield this.request(`${this.prefix}set_current_buf`, [buffer]);
|
|
});
|
|
}
|
|
get chans() {
|
|
return this.request(`${this.prefix}list_chans`);
|
|
}
|
|
getChanInfo(chan) {
|
|
return this.request(`${this.prefix}get_chan_info`, [chan]);
|
|
}
|
|
createNamespace(name = "") {
|
|
return this.request(`${this.prefix}create_namespace`, [name]);
|
|
}
|
|
get namespaces() {
|
|
return this.request(`${this.prefix}get_namespaces`, [name]);
|
|
}
|
|
get commands() {
|
|
return this.getCommands();
|
|
}
|
|
getCommands(options = {}) {
|
|
return this.request(`${this.prefix}get_commands`, [options]);
|
|
}
|
|
/** Get list of all tabpages */
|
|
get tabpages() {
|
|
return this.request(`${this.prefix}list_tabpages`);
|
|
}
|
|
/** Get current tabpage */
|
|
get tabpage() {
|
|
return this.request(`${this.prefix}get_current_tabpage`);
|
|
}
|
|
/** Set current tabpage */
|
|
setTabpage(tabpage) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
yield this.request(`${this.prefix}set_current_tabpage`, [tabpage]);
|
|
});
|
|
}
|
|
/** Get list of all windows */
|
|
get windows() {
|
|
return this.getWindows();
|
|
}
|
|
/** Get current window */
|
|
get window() {
|
|
return this.request(`${this.prefix}get_current_win`);
|
|
}
|
|
/** Get list of all windows */
|
|
getWindows() {
|
|
return this.request(`${this.prefix}list_wins`);
|
|
}
|
|
setWindow(win) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
// Throw error if win is not instance of Window?
|
|
yield this.request(`${this.prefix}set_current_win`, [win]);
|
|
});
|
|
}
|
|
/** Get list of all runtime paths */
|
|
get runtimePaths() {
|
|
return this.request(`${this.prefix}list_runtime_paths`);
|
|
}
|
|
/** Set current directory */
|
|
setDirectory(dir) {
|
|
return this.request(`${this.prefix}set_current_dir`, [dir]);
|
|
}
|
|
/** Get current line. Always returns a Promise. */
|
|
get line() {
|
|
return this.getLine();
|
|
}
|
|
createNewBuffer(listed = false, scratch = false) {
|
|
return this.request(`${this.prefix}create_buf`, [listed, scratch]);
|
|
}
|
|
openFloatWindow(buffer, enter, options) {
|
|
return this.request(`${this.prefix}open_win`, [buffer, enter, options]);
|
|
}
|
|
getLine() {
|
|
return this.request(`${this.prefix}get_current_line`);
|
|
}
|
|
/** Set current line */
|
|
setLine(line) {
|
|
return this.request(`${this.prefix}set_current_line`, [line]);
|
|
}
|
|
/** Gets keymap */
|
|
getKeymap(mode) {
|
|
return this.request(`${this.prefix}get_keymap`, [mode]);
|
|
}
|
|
/** Gets current mode */
|
|
get mode() {
|
|
return this.request(`${this.prefix}get_mode`);
|
|
}
|
|
/** Gets map of defined colors */
|
|
get colorMap() {
|
|
return this.request(`${this.prefix}get_color_map`);
|
|
}
|
|
/** Get color by name */
|
|
getColorByName(name) {
|
|
return this.request(`${this.prefix}get_color_by_name`, [name]);
|
|
}
|
|
/** Get highlight by name or id */
|
|
getHighlight(nameOrId, isRgb = true) {
|
|
const functionName = typeof nameOrId === 'string' ? 'by_name' : 'by_id';
|
|
return this.request(`${this.prefix}get_hl_${functionName}`, [
|
|
nameOrId,
|
|
isRgb,
|
|
]);
|
|
}
|
|
getHighlightByName(name, isRgb = true) {
|
|
return this.request(`${this.prefix}get_hl_by_name`, [name, isRgb]);
|
|
}
|
|
getHighlightById(id, isRgb = true) {
|
|
return this.request(`${this.prefix}get_hl_by_id`, [id, isRgb]);
|
|
}
|
|
/** Delete current line in buffer */
|
|
deleteCurrentLine() {
|
|
return this.request(`${this.prefix}del_current_line`);
|
|
}
|
|
/**
|
|
* Evaluates a VimL expression (:help expression). Dictionaries
|
|
* and Lists are recursively expanded. On VimL error: Returns a
|
|
* generic error; v:errmsg is not updated.
|
|
*
|
|
*/
|
|
eval(expr) {
|
|
return this.request(`${this.prefix}eval`, [expr]);
|
|
}
|
|
/**
|
|
* Executes lua, it's possible neovim client does not support this
|
|
*/
|
|
lua(code, args = []) {
|
|
const _args = this.getArgs(args);
|
|
return this.request(`${this.prefix}execute_lua`, [code, _args]);
|
|
}
|
|
// Alias for `lua()` to be consistent with neovim API
|
|
executeLua(code, args = []) {
|
|
return this.lua(code, args);
|
|
}
|
|
callDictFunction(dict, fname, args = []) {
|
|
const _args = this.getArgs(args);
|
|
return this.request(`${this.prefix}call_dict_function`, [
|
|
dict,
|
|
fname,
|
|
_args,
|
|
]);
|
|
}
|
|
call(fname, args = [], isNotify) {
|
|
const _args = this.getArgs(args);
|
|
if (isNotify) {
|
|
this.notify(`${this.prefix}call_function`, [fname, _args]);
|
|
return null;
|
|
}
|
|
return this.request(`${this.prefix}call_function`, [fname, _args]);
|
|
}
|
|
callTimer(fname, args = [], isNotify) {
|
|
const _args = this.getArgs(args);
|
|
if (isNotify) {
|
|
this.notify(`${this.prefix}call_function`, ['coc#util#timer', [fname, _args]]);
|
|
return null;
|
|
}
|
|
if (isVim) {
|
|
this.notify(`${this.prefix}call_function`, ['coc#util#timer', [fname, _args]]);
|
|
return new Promise(resolve => {
|
|
setTimeout(() => {
|
|
resolve(null);
|
|
}, 20);
|
|
});
|
|
}
|
|
return this.request(`${this.prefix}call_function`, ['coc#util#timer', [fname, _args]]);
|
|
}
|
|
callAsync(fname, args = []) {
|
|
const _args = this.getArgs(args);
|
|
return this.client.sendAsyncRequest(fname, _args);
|
|
}
|
|
/** Alias for `call` */
|
|
callFunction(fname, args = []) {
|
|
return this.call(fname, args);
|
|
}
|
|
/** Call Atomic calls */
|
|
callAtomic(calls) {
|
|
return this.request(`${this.prefix}call_atomic`, [calls]);
|
|
}
|
|
command(arg, isNotify) {
|
|
if (isNotify) {
|
|
this.notify(`${this.prefix}command`, [arg]);
|
|
return null;
|
|
}
|
|
return this.request(`${this.prefix}command`, [arg]);
|
|
}
|
|
/** Runs a command and returns output (synchronous?) */
|
|
commandOutput(arg) {
|
|
return this.request(`${this.prefix}command_output`, [arg]);
|
|
}
|
|
/** Gets a v: variable */
|
|
getVvar(name) {
|
|
return this.request(`${this.prefix}get_vvar`, [name]);
|
|
}
|
|
/** feedKeys */
|
|
feedKeys(keys, mode, escapeCsi) {
|
|
return this.request(`${this.prefix}feedkeys`, [keys, mode, escapeCsi]);
|
|
}
|
|
/** Sends input keys */
|
|
input(keys) {
|
|
return this.request(`${this.prefix}input`, [keys]);
|
|
}
|
|
/**
|
|
* Parse a VimL Expression
|
|
*
|
|
* TODO: return type, see :help
|
|
*/
|
|
parseExpression(expr, flags, highlight) {
|
|
return this.request(`${this.prefix}parse_expression`, [
|
|
expr,
|
|
flags,
|
|
highlight,
|
|
]);
|
|
}
|
|
getProc(pid) {
|
|
return this.request(`${this.prefix}get_proc`, [pid]);
|
|
}
|
|
getProcChildren(pid) {
|
|
return this.request(`${this.prefix}get_proc_children`, [pid]);
|
|
}
|
|
/** Replace term codes */
|
|
replaceTermcodes(str, fromPart, doIt, special) {
|
|
return this.request(`${this.prefix}replace_termcodes`, [
|
|
str,
|
|
fromPart,
|
|
doIt,
|
|
special,
|
|
]);
|
|
}
|
|
/** Gets width of string */
|
|
strWidth(str) {
|
|
return this.request(`${this.prefix}strwidth`, [str]);
|
|
}
|
|
/** Write to output buffer */
|
|
outWrite(str) {
|
|
this.notify(`${this.prefix}out_write`, [str]);
|
|
}
|
|
outWriteLine(str) {
|
|
this.outWrite(`${str}\n`);
|
|
}
|
|
/** Write to error buffer */
|
|
errWrite(str) {
|
|
this.notify(`${this.prefix}err_write`, [str]);
|
|
}
|
|
/** Write to error buffer */
|
|
errWriteLine(str) {
|
|
this.notify(`${this.prefix}err_writeln`, [str]);
|
|
}
|
|
// TODO: add type
|
|
get uis() {
|
|
return this.request(`${this.prefix}list_uis`);
|
|
}
|
|
uiAttach(width, height, options) {
|
|
return this.request(`${this.prefix}ui_attach`, [width, height, options]);
|
|
}
|
|
uiDetach() {
|
|
return this.request(`${this.prefix}ui_detach`, []);
|
|
}
|
|
uiTryResize(width, height) {
|
|
return this.request(`${this.prefix}ui_try_resize`, [width, height]);
|
|
}
|
|
/** Set UI Option */
|
|
uiSetOption(name, value) {
|
|
return this.request(`${this.prefix}ui_set_option`, [name, value]);
|
|
}
|
|
/** Subscribe to nvim event broadcasts */
|
|
subscribe(event) {
|
|
return this.request(`${this.prefix}subscribe`, [event]);
|
|
}
|
|
/** Unsubscribe to nvim event broadcasts */
|
|
unsubscribe(event) {
|
|
return this.request(`${this.prefix}unsubscribe`, [event]);
|
|
}
|
|
setClientInfo(name, version, type, methods, attributes) {
|
|
this.notify(`${this.prefix}set_client_info`, [
|
|
name,
|
|
version,
|
|
type,
|
|
methods,
|
|
attributes,
|
|
]);
|
|
}
|
|
/** Quit nvim */
|
|
quit() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
this.command('qa!', true);
|
|
if (this.transport) {
|
|
this.transport.detach();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
exports.Neovim = Neovim;
|
|
|
|
|
|
/***/ }),
|
|
/* 63 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
var client_1 = __webpack_require__(7);
|
|
exports.Neovim = client_1.NeovimClient;
|
|
var client_2 = __webpack_require__(7);
|
|
exports.NeovimClient = client_2.NeovimClient;
|
|
var Buffer_1 = __webpack_require__(47);
|
|
exports.Buffer = Buffer_1.Buffer;
|
|
var Window_1 = __webpack_require__(50);
|
|
exports.Window = Window_1.Window;
|
|
var Tabpage_1 = __webpack_require__(52);
|
|
exports.Tabpage = Tabpage_1.Tabpage;
|
|
|
|
|
|
/***/ }),
|
|
/* 64 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @fileoverview log4js is a library to log in JavaScript in similar manner
|
|
* than in log4j for Java (but not really).
|
|
*
|
|
* <h3>Example:</h3>
|
|
* <pre>
|
|
* const logging = require('log4js');
|
|
* const log = logging.getLogger('some-category');
|
|
*
|
|
* //call the log
|
|
* log.trace('trace me' );
|
|
* </pre>
|
|
*
|
|
* NOTE: the authors below are the original browser-based log4js authors
|
|
* don't try to contact them about bugs in this version :)
|
|
* @author Stephan Strittmatter - http://jroller.com/page/stritti
|
|
* @author Seth Chisamore - http://www.chisamore.com
|
|
* @since 2005-05-20
|
|
* Website: http://log4js.berlios.de
|
|
*/
|
|
const debug = __webpack_require__(65)("log4js:main");
|
|
const fs = __webpack_require__(55);
|
|
const deepClone = __webpack_require__(73)({ proto: true });
|
|
const configuration = __webpack_require__(74);
|
|
const layouts = __webpack_require__(75);
|
|
const levels = __webpack_require__(77);
|
|
const appenders = __webpack_require__(78);
|
|
const categories = __webpack_require__(145);
|
|
const Logger = __webpack_require__(146);
|
|
const clustering = __webpack_require__(79);
|
|
const connectLogger = __webpack_require__(147);
|
|
|
|
let enabled = false;
|
|
|
|
function sendLogEventToAppender(logEvent) {
|
|
if (!enabled) return;
|
|
debug("Received log event ", logEvent);
|
|
const categoryAppenders = categories.appendersForCategory(
|
|
logEvent.categoryName
|
|
);
|
|
categoryAppenders.forEach(appender => {
|
|
appender(logEvent);
|
|
});
|
|
}
|
|
|
|
function loadConfigurationFile(filename) {
|
|
debug(`Loading configuration from ${filename}`);
|
|
try {
|
|
return JSON.parse(fs.readFileSync(filename, "utf8"));
|
|
} catch (e) {
|
|
throw new Error(
|
|
`Problem reading config from file "${filename}". Error was ${e.message}`,
|
|
e
|
|
);
|
|
}
|
|
}
|
|
|
|
function configure(configurationFileOrObject) {
|
|
let configObject = configurationFileOrObject;
|
|
|
|
if (typeof configObject === "string") {
|
|
configObject = loadConfigurationFile(configurationFileOrObject);
|
|
}
|
|
debug(`Configuration is ${configObject}`);
|
|
|
|
configuration.configure(deepClone(configObject));
|
|
|
|
clustering.onMessage(sendLogEventToAppender);
|
|
|
|
enabled = true;
|
|
|
|
// eslint-disable-next-line no-use-before-define
|
|
return log4js;
|
|
}
|
|
|
|
/**
|
|
* Shutdown all log appenders. This will first disable all writing to appenders
|
|
* and then call the shutdown function each appender.
|
|
*
|
|
* @params {Function} cb - The callback to be invoked once all appenders have
|
|
* shutdown. If an error occurs, the callback will be given the error object
|
|
* as the first argument.
|
|
*/
|
|
function shutdown(cb) {
|
|
debug("Shutdown called. Disabling all log writing.");
|
|
// First, disable all writing to appenders. This prevents appenders from
|
|
// not being able to be drained because of run-away log writes.
|
|
enabled = false;
|
|
|
|
// Call each of the shutdown functions in parallel
|
|
const appendersToCheck = Array.from(appenders.values());
|
|
const shutdownFunctions = appendersToCheck.reduceRight(
|
|
(accum, next) => (next.shutdown ? accum + 1 : accum),
|
|
0
|
|
);
|
|
let completed = 0;
|
|
let error;
|
|
|
|
debug(`Found ${shutdownFunctions} appenders with shutdown functions.`);
|
|
function complete(err) {
|
|
error = error || err;
|
|
completed += 1;
|
|
debug(`Appender shutdowns complete: ${completed} / ${shutdownFunctions}`);
|
|
if (completed >= shutdownFunctions) {
|
|
debug("All shutdown functions completed.");
|
|
cb(error);
|
|
}
|
|
}
|
|
|
|
if (shutdownFunctions === 0) {
|
|
debug("No appenders with shutdown functions found.");
|
|
return cb();
|
|
}
|
|
|
|
appendersToCheck.filter(a => a.shutdown).forEach(a => a.shutdown(complete));
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get a logger instance.
|
|
* @static
|
|
* @param loggerCategoryName
|
|
* @return {Logger} instance of logger for the category
|
|
*/
|
|
function getLogger(category) {
|
|
if (!enabled) {
|
|
configure(
|
|
process.env.LOG4JS_CONFIG || {
|
|
appenders: { out: { type: "stdout" } },
|
|
categories: { default: { appenders: ["out"], level: "OFF" } }
|
|
}
|
|
);
|
|
}
|
|
return new Logger(category || "default");
|
|
}
|
|
|
|
/**
|
|
* @name log4js
|
|
* @namespace Log4js
|
|
* @property getLogger
|
|
* @property configure
|
|
* @property shutdown
|
|
*/
|
|
const log4js = {
|
|
getLogger,
|
|
configure,
|
|
shutdown,
|
|
connectLogger,
|
|
levels,
|
|
addLayout: layouts.addLayout
|
|
};
|
|
|
|
module.exports = log4js;
|
|
|
|
|
|
/***/ }),
|
|
/* 65 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* 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__(66);
|
|
} else {
|
|
module.exports = __webpack_require__(69);
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 66 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* eslint-env browser */
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
|
|
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
|
|
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.
|
|
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 (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
|
|
*/
|
|
|
|
function formatArgs(args) {
|
|
args[0] = (this.useColors ? '%c' : '') +
|
|
this.namespace +
|
|
(this.useColors ? ' %c' : ' ') +
|
|
args[0] +
|
|
(this.useColors ? '%c ' : ' ') +
|
|
'+' + module.exports.humanize(this.diff);
|
|
|
|
if (!this.useColors) {
|
|
return;
|
|
}
|
|
|
|
const 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
|
|
let index = 0;
|
|
let lastC = 0;
|
|
args[0].replace(/%[a-zA-Z%]/g, match => {
|
|
if (match === '%%') {
|
|
return;
|
|
}
|
|
index++;
|
|
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
|
|
*/
|
|
function log(...args) {
|
|
// This hackery is required for IE8/9, where
|
|
// the `console.log` function doesn't have 'apply'
|
|
return typeof console === 'object' &&
|
|
console.log &&
|
|
console.log(...args);
|
|
}
|
|
|
|
/**
|
|
* Save `namespaces`.
|
|
*
|
|
* @param {String} namespaces
|
|
* @api private
|
|
*/
|
|
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
|
|
*/
|
|
function load() {
|
|
let r;
|
|
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
|
|
if (!r && typeof process !== 'undefined' && 'env' in process) {
|
|
r = process.env.DEBUG;
|
|
}
|
|
|
|
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
|
|
*/
|
|
|
|
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?
|
|
}
|
|
}
|
|
|
|
module.exports = __webpack_require__(67)(exports);
|
|
|
|
const {formatters} = module.exports;
|
|
|
|
/**
|
|
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
|
|
*/
|
|
|
|
formatters.j = function (v) {
|
|
try {
|
|
return JSON.stringify(v);
|
|
} catch (error) {
|
|
return '[UnexpectedJSONParseError]: ' + error.message;
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 67 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
|
|
/**
|
|
* 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__(68);
|
|
|
|
Object.keys(env).forEach(key => {
|
|
createDebug[key] = env[key];
|
|
});
|
|
|
|
/**
|
|
* Active `debug` instances.
|
|
*/
|
|
createDebug.instances = [];
|
|
|
|
/**
|
|
* The currently active debug mode names, and names to skip.
|
|
*/
|
|
|
|
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".
|
|
*/
|
|
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) {
|
|
let hash = 0;
|
|
|
|
for (let i = 0; i < namespace.length; i++) {
|
|
hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
|
|
hash |= 0; // Convert to 32bit integer
|
|
}
|
|
|
|
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) {
|
|
let prevTime;
|
|
|
|
function debug(...args) {
|
|
// Disabled?
|
|
if (!debug.enabled) {
|
|
return;
|
|
}
|
|
|
|
const self = debug;
|
|
|
|
// Set `diff` timestamp
|
|
const curr = Number(new Date());
|
|
const 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
|
|
let index = 0;
|
|
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
|
|
// If we encounter an escaped % then don't increase the array index
|
|
if (match === '%%') {
|
|
return match;
|
|
}
|
|
index++;
|
|
const formatter = createDebug.formatters[format];
|
|
if (typeof formatter === 'function') {
|
|
const val = args[index];
|
|
match = formatter.call(self, val);
|
|
|
|
// Now we need to remove `args[index]` since it's inlined in the `format`
|
|
args.splice(index, 1);
|
|
index--;
|
|
}
|
|
return match;
|
|
});
|
|
|
|
// Apply env-specific formatting (colors, etc.)
|
|
createDebug.formatArgs.call(self, args);
|
|
|
|
const logFn = self.log || createDebug.log;
|
|
logFn.apply(self, args);
|
|
}
|
|
|
|
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 (typeof createDebug.init === 'function') {
|
|
createDebug.init(debug);
|
|
}
|
|
|
|
createDebug.instances.push(debug);
|
|
|
|
return debug;
|
|
}
|
|
|
|
function destroy() {
|
|
const index = createDebug.instances.indexOf(this);
|
|
if (index !== -1) {
|
|
createDebug.instances.splice(index, 1);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function extend(namespace, delimiter) {
|
|
const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
|
|
newDebug.log = this.log;
|
|
return newDebug;
|
|
}
|
|
|
|
/**
|
|
* Enables a debug mode by namespaces. This can include modes
|
|
* separated by a colon and wildcards.
|
|
*
|
|
* @param {String} namespaces
|
|
* @api public
|
|
*/
|
|
function enable(namespaces) {
|
|
createDebug.save(namespaces);
|
|
|
|
createDebug.names = [];
|
|
createDebug.skips = [];
|
|
|
|
let i;
|
|
const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
|
|
const len = split.length;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if (!split[i]) {
|
|
// ignore empty strings
|
|
continue;
|
|
}
|
|
|
|
namespaces = split[i].replace(/\*/g, '.*?');
|
|
|
|
if (namespaces[0] === '-') {
|
|
createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
|
|
} else {
|
|
createDebug.names.push(new RegExp('^' + namespaces + '$'));
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < createDebug.instances.length; i++) {
|
|
const instance = createDebug.instances[i];
|
|
instance.enabled = createDebug.enabled(instance.namespace);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disable debug output.
|
|
*
|
|
* @return {String} namespaces
|
|
* @api public
|
|
*/
|
|
function disable() {
|
|
const namespaces = [
|
|
...createDebug.names.map(toNamespace),
|
|
...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace)
|
|
].join(',');
|
|
createDebug.enable('');
|
|
return namespaces;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the given mode name is enabled, false otherwise.
|
|
*
|
|
* @param {String} name
|
|
* @return {Boolean}
|
|
* @api public
|
|
*/
|
|
function enabled(name) {
|
|
if (name[name.length - 1] === '*') {
|
|
return true;
|
|
}
|
|
|
|
let i;
|
|
let len;
|
|
|
|
for (i = 0, len = createDebug.skips.length; i < len; i++) {
|
|
if (createDebug.skips[i].test(name)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
for (i = 0, len = createDebug.names.length; i < len; i++) {
|
|
if (createDebug.names[i].test(name)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Convert regexp to namespace
|
|
*
|
|
* @param {RegExp} regxep
|
|
* @return {String} namespace
|
|
* @api private
|
|
*/
|
|
function toNamespace(regexp) {
|
|
return regexp.toString()
|
|
.substring(2, regexp.toString().length - 2)
|
|
.replace(/\.\*\?$/, '*');
|
|
}
|
|
|
|
/**
|
|
* Coerce `val`.
|
|
*
|
|
* @param {Mixed} val
|
|
* @return {Mixed}
|
|
* @api private
|
|
*/
|
|
function coerce(val) {
|
|
if (val instanceof Error) {
|
|
return val.stack || val.message;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
createDebug.enable(createDebug.load());
|
|
|
|
return createDebug;
|
|
}
|
|
|
|
module.exports = setup;
|
|
|
|
|
|
/***/ }),
|
|
/* 68 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* Helpers.
|
|
*/
|
|
|
|
var s = 1000;
|
|
var m = s * 60;
|
|
var h = m * 60;
|
|
var d = h * 24;
|
|
var w = d * 7;
|
|
var y = d * 365.25;
|
|
|
|
/**
|
|
* Parse or format the given `val`.
|
|
*
|
|
* Options:
|
|
*
|
|
* - `long` verbose formatting [false]
|
|
*
|
|
* @param {String|Number} val
|
|
* @param {Object} [options]
|
|
* @throws {Error} throw an error if val is not a non-empty string or a number
|
|
* @return {String|Number}
|
|
* @api public
|
|
*/
|
|
|
|
module.exports = function(val, options) {
|
|
options = options || {};
|
|
var type = typeof val;
|
|
if (type === 'string' && val.length > 0) {
|
|
return parse(val);
|
|
} else if (type === 'number' && isFinite(val)) {
|
|
return options.long ? fmtLong(val) : fmtShort(val);
|
|
}
|
|
throw new Error(
|
|
'val is not a non-empty string or a valid number. val=' +
|
|
JSON.stringify(val)
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Parse the given `str` and return milliseconds.
|
|
*
|
|
* @param {String} str
|
|
* @return {Number}
|
|
* @api private
|
|
*/
|
|
|
|
function parse(str) {
|
|
str = String(str);
|
|
if (str.length > 100) {
|
|
return;
|
|
}
|
|
var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
|
|
str
|
|
);
|
|
if (!match) {
|
|
return;
|
|
}
|
|
var n = parseFloat(match[1]);
|
|
var type = (match[2] || 'ms').toLowerCase();
|
|
switch (type) {
|
|
case 'years':
|
|
case 'year':
|
|
case 'yrs':
|
|
case 'yr':
|
|
case 'y':
|
|
return n * y;
|
|
case 'weeks':
|
|
case 'week':
|
|
case 'w':
|
|
return n * w;
|
|
case 'days':
|
|
case 'day':
|
|
case 'd':
|
|
return n * d;
|
|
case 'hours':
|
|
case 'hour':
|
|
case 'hrs':
|
|
case 'hr':
|
|
case 'h':
|
|
return n * h;
|
|
case 'minutes':
|
|
case 'minute':
|
|
case 'mins':
|
|
case 'min':
|
|
case 'm':
|
|
return n * m;
|
|
case 'seconds':
|
|
case 'second':
|
|
case 'secs':
|
|
case 'sec':
|
|
case 's':
|
|
return n * s;
|
|
case 'milliseconds':
|
|
case 'millisecond':
|
|
case 'msecs':
|
|
case 'msec':
|
|
case 'ms':
|
|
return n;
|
|
default:
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Short format for `ms`.
|
|
*
|
|
* @param {Number} ms
|
|
* @return {String}
|
|
* @api private
|
|
*/
|
|
|
|
function fmtShort(ms) {
|
|
var msAbs = Math.abs(ms);
|
|
if (msAbs >= d) {
|
|
return Math.round(ms / d) + 'd';
|
|
}
|
|
if (msAbs >= h) {
|
|
return Math.round(ms / h) + 'h';
|
|
}
|
|
if (msAbs >= m) {
|
|
return Math.round(ms / m) + 'm';
|
|
}
|
|
if (msAbs >= s) {
|
|
return Math.round(ms / s) + 's';
|
|
}
|
|
return ms + 'ms';
|
|
}
|
|
|
|
/**
|
|
* Long format for `ms`.
|
|
*
|
|
* @param {Number} ms
|
|
* @return {String}
|
|
* @api private
|
|
*/
|
|
|
|
function fmtLong(ms) {
|
|
var msAbs = Math.abs(ms);
|
|
if (msAbs >= d) {
|
|
return plural(ms, msAbs, d, 'day');
|
|
}
|
|
if (msAbs >= h) {
|
|
return plural(ms, msAbs, h, 'hour');
|
|
}
|
|
if (msAbs >= m) {
|
|
return plural(ms, msAbs, m, 'minute');
|
|
}
|
|
if (msAbs >= s) {
|
|
return plural(ms, msAbs, s, 'second');
|
|
}
|
|
return ms + ' ms';
|
|
}
|
|
|
|
/**
|
|
* Pluralization helper.
|
|
*/
|
|
|
|
function plural(ms, msAbs, n, name) {
|
|
var isPlural = msAbs >= n * 1.5;
|
|
return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 69 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* Module dependencies.
|
|
*/
|
|
|
|
const tty = __webpack_require__(70);
|
|
const util = __webpack_require__(40);
|
|
|
|
/**
|
|
* 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
|
|
const supportsColor = __webpack_require__(71);
|
|
|
|
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.
|
|
}
|
|
|
|
/**
|
|
* Build up the default `inspectOpts` object from the environment variables.
|
|
*
|
|
* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
|
|
*/
|
|
|
|
exports.inspectOpts = Object.keys(process.env).filter(key => {
|
|
return /^debug_/i.test(key);
|
|
}).reduce((obj, key) => {
|
|
// Camel-case
|
|
const prop = key
|
|
.substring(6)
|
|
.toLowerCase()
|
|
.replace(/_([a-z])/g, (_, k) => {
|
|
return k.toUpperCase();
|
|
});
|
|
|
|
// Coerce string value into JS value
|
|
let 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 {
|
|
val = Number(val);
|
|
}
|
|
|
|
obj[prop] = val;
|
|
return obj;
|
|
}, {});
|
|
|
|
/**
|
|
* Is stdout a TTY? Colored output is enabled when `true`.
|
|
*/
|
|
|
|
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
|
|
*/
|
|
|
|
function formatArgs(args) {
|
|
const {namespace: name, useColors} = this;
|
|
|
|
if (useColors) {
|
|
const c = this.color;
|
|
const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c);
|
|
const prefix = ` ${colorCode};1m${name} \u001B[0m`;
|
|
|
|
args[0] = prefix + args[0].split('\n').join('\n' + prefix);
|
|
args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m');
|
|
} else {
|
|
args[0] = getDate() + name + ' ' + args[0];
|
|
}
|
|
}
|
|
|
|
function getDate() {
|
|
if (exports.inspectOpts.hideDate) {
|
|
return '';
|
|
}
|
|
return new Date().toISOString() + ' ';
|
|
}
|
|
|
|
/**
|
|
* Invokes `util.format()` with the specified arguments and writes to stderr.
|
|
*/
|
|
|
|
function log(...args) {
|
|
return process.stderr.write(util.format(...args) + '\n');
|
|
}
|
|
|
|
/**
|
|
* Save `namespaces`.
|
|
*
|
|
* @param {String} namespaces
|
|
* @api private
|
|
*/
|
|
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
|
|
*/
|
|
|
|
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 init(debug) {
|
|
debug.inspectOpts = {};
|
|
|
|
const keys = Object.keys(exports.inspectOpts);
|
|
for (let i = 0; i < keys.length; i++) {
|
|
debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
|
|
}
|
|
}
|
|
|
|
module.exports = __webpack_require__(67)(exports);
|
|
|
|
const {formatters} = module.exports;
|
|
|
|
/**
|
|
* 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);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 70 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("tty");
|
|
|
|
/***/ }),
|
|
/* 71 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
const os = __webpack_require__(56);
|
|
const hasFlag = __webpack_require__(72);
|
|
|
|
const {env} = process;
|
|
|
|
let forceColor;
|
|
if (hasFlag('no-color') ||
|
|
hasFlag('no-colors') ||
|
|
hasFlag('color=false') ||
|
|
hasFlag('color=never')) {
|
|
forceColor = 0;
|
|
} else if (hasFlag('color') ||
|
|
hasFlag('colors') ||
|
|
hasFlag('color=true') ||
|
|
hasFlag('color=always')) {
|
|
forceColor = 1;
|
|
}
|
|
if ('FORCE_COLOR' in env) {
|
|
if (env.FORCE_COLOR === true || env.FORCE_COLOR === 'true') {
|
|
forceColor = 1;
|
|
} else if (env.FORCE_COLOR === false || env.FORCE_COLOR === 'false') {
|
|
forceColor = 0;
|
|
} else {
|
|
forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
|
|
}
|
|
}
|
|
|
|
function translateLevel(level) {
|
|
if (level === 0) {
|
|
return false;
|
|
}
|
|
|
|
return {
|
|
level,
|
|
hasBasic: true,
|
|
has256: level >= 2,
|
|
has16m: level >= 3
|
|
};
|
|
}
|
|
|
|
function supportsColor(stream) {
|
|
if (forceColor === 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (hasFlag('color=16m') ||
|
|
hasFlag('color=full') ||
|
|
hasFlag('color=truecolor')) {
|
|
return 3;
|
|
}
|
|
|
|
if (hasFlag('color=256')) {
|
|
return 2;
|
|
}
|
|
|
|
if (stream && !stream.isTTY && forceColor === undefined) {
|
|
return 0;
|
|
}
|
|
|
|
const min = forceColor || 0;
|
|
|
|
if (env.TERM === 'dumb') {
|
|
return min;
|
|
}
|
|
|
|
if (process.platform === 'win32') {
|
|
// Node.js 7.5.0 is the first version of Node.js to include a patch to
|
|
// libuv that enables 256 color output on Windows. Anything earlier and it
|
|
// won't work. However, here we target Node.js 8 at minimum as it is an LTS
|
|
// release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows
|
|
// release that supports 256 colors. Windows 10 build 14931 is the first release
|
|
// that supports 16m/TrueColor.
|
|
const osRelease = os.release().split('.');
|
|
if (
|
|
Number(process.versions.node.split('.')[0]) >= 8 &&
|
|
Number(osRelease[0]) >= 10 &&
|
|
Number(osRelease[2]) >= 10586
|
|
) {
|
|
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
if ('CI' in env) {
|
|
if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
|
|
return 1;
|
|
}
|
|
|
|
return min;
|
|
}
|
|
|
|
if ('TEAMCITY_VERSION' in env) {
|
|
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
}
|
|
|
|
if (env.COLORTERM === 'truecolor') {
|
|
return 3;
|
|
}
|
|
|
|
if ('TERM_PROGRAM' in env) {
|
|
const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
|
|
|
|
switch (env.TERM_PROGRAM) {
|
|
case 'iTerm.app':
|
|
return version >= 3 ? 3 : 2;
|
|
case 'Apple_Terminal':
|
|
return 2;
|
|
// No default
|
|
}
|
|
}
|
|
|
|
if (/-256(color)?$/i.test(env.TERM)) {
|
|
return 2;
|
|
}
|
|
|
|
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|
return 1;
|
|
}
|
|
|
|
if ('COLORTERM' in env) {
|
|
return 1;
|
|
}
|
|
|
|
return min;
|
|
}
|
|
|
|
function getSupportLevel(stream) {
|
|
const level = supportsColor(stream);
|
|
return translateLevel(level);
|
|
}
|
|
|
|
module.exports = {
|
|
supportsColor: getSupportLevel,
|
|
stdout: getSupportLevel(process.stdout),
|
|
stderr: getSupportLevel(process.stderr)
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 72 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
module.exports = (flag, argv) => {
|
|
argv = argv || process.argv;
|
|
const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');
|
|
const pos = argv.indexOf(prefix + flag);
|
|
const terminatorPos = argv.indexOf('--');
|
|
return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 73 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
module.exports = rfdc
|
|
|
|
function rfdc (opts) {
|
|
opts = opts || {}
|
|
|
|
if (opts.circles) return rfdcCircles(opts)
|
|
return opts.proto ? cloneProto : clone
|
|
|
|
function cloneArray (a, fn) {
|
|
var keys = Object.keys(a)
|
|
var a2 = new Array(keys.length)
|
|
for (var i = 0; i < keys.length; i++) {
|
|
var k = keys[i]
|
|
var cur = a[k]
|
|
if (typeof cur !== 'object' || cur === null) {
|
|
a2[k] = cur
|
|
} else if (cur instanceof Date) {
|
|
a2[k] = new Date(cur)
|
|
} else {
|
|
a2[k] = fn(cur)
|
|
}
|
|
}
|
|
return a2
|
|
}
|
|
|
|
function clone (o) {
|
|
if (typeof o !== 'object' || o === null) return o
|
|
if (o instanceof Date) return new Date(o)
|
|
if (Array.isArray(o)) return cloneArray(o, clone)
|
|
var o2 = {}
|
|
for (var k in o) {
|
|
if (Object.hasOwnProperty.call(o, k) === false) continue
|
|
var cur = o[k]
|
|
if (typeof cur !== 'object' || cur === null) {
|
|
o2[k] = cur
|
|
} else if (cur instanceof Date) {
|
|
o2[k] = new Date(cur)
|
|
} else {
|
|
o2[k] = clone(cur)
|
|
}
|
|
}
|
|
return o2
|
|
}
|
|
|
|
function cloneProto (o) {
|
|
if (typeof o !== 'object' || o === null) return o
|
|
if (o instanceof Date) return new Date(o)
|
|
if (Array.isArray(o)) return cloneArray(o, cloneProto)
|
|
var o2 = {}
|
|
for (var k in o) {
|
|
var cur = o[k]
|
|
if (typeof cur !== 'object' || cur === null) {
|
|
o2[k] = cur
|
|
} else if (cur instanceof Date) {
|
|
o2[k] = new Date(cur)
|
|
} else {
|
|
o2[k] = cloneProto(cur)
|
|
}
|
|
}
|
|
return o2
|
|
}
|
|
}
|
|
|
|
function rfdcCircles (opts) {
|
|
var refs = []
|
|
var refsNew = []
|
|
|
|
return opts.proto ? cloneProto : clone
|
|
|
|
function cloneArray (a, fn) {
|
|
var keys = Object.keys(a)
|
|
var a2 = new Array(keys.length)
|
|
for (var i = 0; i < keys.length; i++) {
|
|
var k = keys[i]
|
|
var cur = a[k]
|
|
if (typeof cur !== 'object' || cur === null) {
|
|
a2[k] = cur
|
|
} else if (cur instanceof Date) {
|
|
a2[k] = new Date(cur)
|
|
} else {
|
|
var index = refs.indexOf(cur)
|
|
if (index !== -1) {
|
|
a2[k] = refsNew[index]
|
|
} else {
|
|
a2[k] = fn(cur)
|
|
}
|
|
}
|
|
}
|
|
return a2
|
|
}
|
|
|
|
function clone (o) {
|
|
if (typeof o !== 'object' || o === null) return o
|
|
if (o instanceof Date) return new Date(o)
|
|
if (Array.isArray(o)) return cloneArray(o, clone)
|
|
var o2 = {}
|
|
refs.push(o)
|
|
refsNew.push(o2)
|
|
for (var k in o) {
|
|
if (Object.hasOwnProperty.call(o, k) === false) continue
|
|
var cur = o[k]
|
|
if (typeof cur !== 'object' || cur === null) {
|
|
o2[k] = cur
|
|
} else if (cur instanceof Date) {
|
|
o2[k] = new Date(cur)
|
|
} else {
|
|
var i = refs.indexOf(cur)
|
|
if (i !== -1) {
|
|
o2[k] = refsNew[i]
|
|
} else {
|
|
o2[k] = clone(cur)
|
|
}
|
|
}
|
|
}
|
|
refs.pop()
|
|
refsNew.pop()
|
|
return o2
|
|
}
|
|
|
|
function cloneProto (o) {
|
|
if (typeof o !== 'object' || o === null) return o
|
|
if (o instanceof Date) return new Date(o)
|
|
if (Array.isArray(o)) return cloneArray(o, cloneProto)
|
|
var o2 = {}
|
|
refs.push(o)
|
|
refsNew.push(o2)
|
|
for (var k in o) {
|
|
var cur = o[k]
|
|
if (typeof cur !== 'object' || cur === null) {
|
|
o2[k] = cur
|
|
} else if (cur instanceof Date) {
|
|
o2[k] = new Date(cur)
|
|
} else {
|
|
var i = refs.indexOf(cur)
|
|
if (i !== -1) {
|
|
o2[k] = refsNew[i]
|
|
} else {
|
|
o2[k] = cloneProto(cur)
|
|
}
|
|
}
|
|
}
|
|
refs.pop()
|
|
refsNew.pop()
|
|
return o2
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 74 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
|
|
|
|
const util = __webpack_require__(40);
|
|
const debug = __webpack_require__(65)('log4js:configuration');
|
|
|
|
const preProcessingListeners = [];
|
|
const listeners = [];
|
|
|
|
const not = thing => !thing;
|
|
|
|
const anObject = thing => thing && typeof thing === 'object' && !Array.isArray(thing);
|
|
|
|
const validIdentifier = thing => /^[A-Za-z][A-Za-z0-9_]*$/g.test(thing);
|
|
|
|
const anInteger = thing => thing && typeof thing === 'number' && Number.isInteger(thing);
|
|
|
|
const addListener = (fn) => {
|
|
listeners.push(fn);
|
|
debug(`Added listener, now ${listeners.length} listeners`);
|
|
};
|
|
|
|
const addPreProcessingListener = (fn) => {
|
|
preProcessingListeners.push(fn);
|
|
debug(`Added pre-processing listener, now ${preProcessingListeners.length} listeners`);
|
|
};
|
|
|
|
const throwExceptionIf = (config, checks, message) => {
|
|
const tests = Array.isArray(checks) ? checks : [checks];
|
|
tests.forEach((test) => {
|
|
if (test) {
|
|
throw new Error(`Problem with log4js configuration: (${util.inspect(config, { depth: 5 })})`
|
|
+ ` - ${message}`);
|
|
}
|
|
});
|
|
};
|
|
|
|
const configure = (candidate) => {
|
|
debug('New configuration to be validated: ', candidate);
|
|
throwExceptionIf(candidate, not(anObject(candidate)), 'must be an object.');
|
|
|
|
debug(`Calling pre-processing listeners (${preProcessingListeners.length})`);
|
|
preProcessingListeners.forEach(listener => listener(candidate));
|
|
debug('Configuration pre-processing finished.');
|
|
|
|
debug(`Calling configuration listeners (${listeners.length})`);
|
|
listeners.forEach(listener => listener(candidate));
|
|
debug('Configuration finished.');
|
|
};
|
|
|
|
module.exports = {
|
|
configure,
|
|
addListener,
|
|
addPreProcessingListener,
|
|
throwExceptionIf,
|
|
anObject,
|
|
anInteger,
|
|
validIdentifier,
|
|
not
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 75 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const dateFormat = __webpack_require__(76);
|
|
const os = __webpack_require__(56);
|
|
const util = __webpack_require__(40);
|
|
const path = __webpack_require__(57);
|
|
|
|
const styles = {
|
|
// styles
|
|
bold: [1, 22],
|
|
italic: [3, 23],
|
|
underline: [4, 24],
|
|
inverse: [7, 27],
|
|
// grayscale
|
|
white: [37, 39],
|
|
grey: [90, 39],
|
|
black: [90, 39],
|
|
// colors
|
|
blue: [34, 39],
|
|
cyan: [36, 39],
|
|
green: [32, 39],
|
|
magenta: [35, 39],
|
|
red: [91, 39],
|
|
yellow: [33, 39]
|
|
};
|
|
|
|
function colorizeStart(style) {
|
|
return style ? `\x1B[${styles[style][0]}m` : '';
|
|
}
|
|
|
|
function colorizeEnd(style) {
|
|
return style ? `\x1B[${styles[style][1]}m` : '';
|
|
}
|
|
|
|
/**
|
|
* Taken from masylum's fork (https://github.com/masylum/log4js-node)
|
|
*/
|
|
function colorize(str, style) {
|
|
return colorizeStart(style) + str + colorizeEnd(style);
|
|
}
|
|
|
|
function timestampLevelAndCategory(loggingEvent, colour) {
|
|
return colorize(
|
|
util.format(
|
|
'[%s] [%s] %s - ',
|
|
dateFormat.asString(loggingEvent.startTime),
|
|
loggingEvent.level.toString(),
|
|
loggingEvent.categoryName
|
|
),
|
|
colour
|
|
);
|
|
}
|
|
|
|
/**
|
|
* BasicLayout is a simple layout for storing the logs. The logs are stored
|
|
* in following format:
|
|
* <pre>
|
|
* [startTime] [logLevel] categoryName - message\n
|
|
* </pre>
|
|
*
|
|
* @author Stephan Strittmatter
|
|
*/
|
|
function basicLayout(loggingEvent) {
|
|
return timestampLevelAndCategory(loggingEvent) + util.format(...loggingEvent.data);
|
|
}
|
|
|
|
/**
|
|
* colouredLayout - taken from masylum's fork.
|
|
* same as basicLayout, but with colours.
|
|
*/
|
|
function colouredLayout(loggingEvent) {
|
|
return timestampLevelAndCategory(loggingEvent, loggingEvent.level.colour) + util.format(...loggingEvent.data);
|
|
}
|
|
|
|
function messagePassThroughLayout(loggingEvent) {
|
|
return util.format(...loggingEvent.data);
|
|
}
|
|
|
|
function dummyLayout(loggingEvent) {
|
|
return loggingEvent.data[0];
|
|
}
|
|
|
|
/**
|
|
* PatternLayout
|
|
* Format for specifiers is %[padding].[truncation][field]{[format]}
|
|
* e.g. %5.10p - left pad the log level by 5 characters, up to a max of 10
|
|
* Fields can be any of:
|
|
* - %r time in toLocaleTimeString format
|
|
* - %p log level
|
|
* - %c log category
|
|
* - %h hostname
|
|
* - %m log data
|
|
* - %d date in constious formats
|
|
* - %% %
|
|
* - %n newline
|
|
* - %z pid
|
|
* - %f filename
|
|
* - %l line number
|
|
* - %o column postion
|
|
* - %s call stack
|
|
* - %x{<tokenname>} add dynamic tokens to your log. Tokens are specified in the tokens parameter
|
|
* - %X{<tokenname>} add dynamic tokens to your log. Tokens are specified in logger context
|
|
* You can use %[ and %] to define a colored block.
|
|
*
|
|
* Tokens are specified as simple key:value objects.
|
|
* The key represents the token name whereas the value can be a string or function
|
|
* which is called to extract the value to put in the log message. If token is not
|
|
* found, it doesn't replace the field.
|
|
*
|
|
* A sample token would be: { 'pid' : function() { return process.pid; } }
|
|
*
|
|
* Takes a pattern string, array of tokens and returns a layout function.
|
|
* @return {Function}
|
|
* @param pattern
|
|
* @param tokens
|
|
* @param timezoneOffset
|
|
*
|
|
* @authors ['Stephan Strittmatter', 'Jan Schmidle']
|
|
*/
|
|
function patternLayout(pattern, tokens) {
|
|
const TTCC_CONVERSION_PATTERN = '%r %p %c - %m%n';
|
|
const regex = /%(-?[0-9]+)?(\.?[0-9]+)?([[\]cdhmnprzxXyflos%])(\{([^}]+)\})?|([^%]+)/;
|
|
|
|
pattern = pattern || TTCC_CONVERSION_PATTERN;
|
|
|
|
function categoryName(loggingEvent, specifier) {
|
|
let loggerName = loggingEvent.categoryName;
|
|
if (specifier) {
|
|
const precision = parseInt(specifier, 10);
|
|
const loggerNameBits = loggerName.split('.');
|
|
if (precision < loggerNameBits.length) {
|
|
loggerName = loggerNameBits.slice(loggerNameBits.length - precision).join('.');
|
|
}
|
|
}
|
|
return loggerName;
|
|
}
|
|
|
|
function formatAsDate(loggingEvent, specifier) {
|
|
let format = dateFormat.ISO8601_FORMAT;
|
|
if (specifier) {
|
|
format = specifier;
|
|
// Pick up special cases
|
|
if (format === 'ISO8601') {
|
|
format = dateFormat.ISO8601_FORMAT;
|
|
} else if (format === 'ISO8601_WITH_TZ_OFFSET') {
|
|
format = dateFormat.ISO8601_WITH_TZ_OFFSET_FORMAT;
|
|
} else if (format === 'ABSOLUTE') {
|
|
format = dateFormat.ABSOLUTETIME_FORMAT;
|
|
} else if (format === 'DATE') {
|
|
format = dateFormat.DATETIME_FORMAT;
|
|
}
|
|
}
|
|
// Format the date
|
|
return dateFormat.asString(format, loggingEvent.startTime);
|
|
}
|
|
|
|
function hostname() {
|
|
return os.hostname().toString();
|
|
}
|
|
|
|
function formatMessage(loggingEvent) {
|
|
return util.format(...loggingEvent.data);
|
|
}
|
|
|
|
function endOfLine() {
|
|
return os.EOL;
|
|
}
|
|
|
|
function logLevel(loggingEvent) {
|
|
return loggingEvent.level.toString();
|
|
}
|
|
|
|
function startTime(loggingEvent) {
|
|
return dateFormat.asString('hh:mm:ss', loggingEvent.startTime);
|
|
}
|
|
|
|
function startColour(loggingEvent) {
|
|
return colorizeStart(loggingEvent.level.colour);
|
|
}
|
|
|
|
function endColour(loggingEvent) {
|
|
return colorizeEnd(loggingEvent.level.colour);
|
|
}
|
|
|
|
function percent() {
|
|
return '%';
|
|
}
|
|
|
|
function pid(loggingEvent) {
|
|
return loggingEvent && loggingEvent.pid ? loggingEvent.pid.toString() : process.pid.toString();
|
|
}
|
|
|
|
function clusterInfo() {
|
|
// this used to try to return the master and worker pids,
|
|
// but it would never have worked because master pid is not available to workers
|
|
// leaving this here to maintain compatibility for patterns
|
|
return pid();
|
|
}
|
|
|
|
function userDefined(loggingEvent, specifier) {
|
|
if (typeof tokens[specifier] !== 'undefined') {
|
|
return typeof tokens[specifier] === 'function' ? tokens[specifier](loggingEvent) : tokens[specifier];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function contextDefined(loggingEvent, specifier) {
|
|
const resolver = loggingEvent.context[specifier];
|
|
|
|
if (typeof resolver !== 'undefined') {
|
|
return typeof resolver === 'function' ? resolver(loggingEvent) : resolver;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function fileName(loggingEvent, specifier) {
|
|
let filename = loggingEvent.fileName || '';
|
|
if (specifier) {
|
|
const fileDepth = parseInt(specifier, 10);
|
|
const fileList = filename.split(path.sep);
|
|
if (fileList.length > fileDepth) {
|
|
filename = fileList.slice(-fileDepth).join(path.sep);
|
|
}
|
|
}
|
|
|
|
return filename;
|
|
}
|
|
|
|
function lineNumber(loggingEvent) {
|
|
return loggingEvent.lineNumber || '';
|
|
}
|
|
|
|
function columnNumber(loggingEvent) {
|
|
return loggingEvent.columnNumber || '';
|
|
}
|
|
|
|
function callStack(loggingEvent) {
|
|
return loggingEvent.callStack || '';
|
|
}
|
|
|
|
/* eslint quote-props:0 */
|
|
const replacers = {
|
|
c: categoryName,
|
|
d: formatAsDate,
|
|
h: hostname,
|
|
m: formatMessage,
|
|
n: endOfLine,
|
|
p: logLevel,
|
|
r: startTime,
|
|
'[': startColour,
|
|
']': endColour,
|
|
y: clusterInfo,
|
|
z: pid,
|
|
'%': percent,
|
|
x: userDefined,
|
|
X: contextDefined,
|
|
f: fileName,
|
|
l: lineNumber,
|
|
o: columnNumber,
|
|
s: callStack
|
|
};
|
|
|
|
function replaceToken(conversionCharacter, loggingEvent, specifier) {
|
|
return replacers[conversionCharacter](loggingEvent, specifier);
|
|
}
|
|
|
|
function truncate(truncation, toTruncate) {
|
|
let len;
|
|
if (truncation) {
|
|
len = parseInt(truncation.substr(1), 10);
|
|
return toTruncate.substring(0, len);
|
|
}
|
|
|
|
return toTruncate;
|
|
}
|
|
|
|
function pad(padding, toPad) {
|
|
let len;
|
|
if (padding) {
|
|
if (padding.charAt(0) === '-') {
|
|
len = parseInt(padding.substr(1), 10);
|
|
// Right pad with spaces
|
|
while (toPad.length < len) {
|
|
toPad += ' ';
|
|
}
|
|
} else {
|
|
len = parseInt(padding, 10);
|
|
// Left pad with spaces
|
|
while (toPad.length < len) {
|
|
toPad = ` ${toPad}`;
|
|
}
|
|
}
|
|
}
|
|
return toPad;
|
|
}
|
|
|
|
function truncateAndPad(toTruncAndPad, truncation, padding) {
|
|
let replacement = toTruncAndPad;
|
|
replacement = truncate(truncation, replacement);
|
|
replacement = pad(padding, replacement);
|
|
return replacement;
|
|
}
|
|
|
|
return function (loggingEvent) {
|
|
let formattedString = '';
|
|
let result;
|
|
let searchString = pattern;
|
|
|
|
/* eslint no-cond-assign:0 */
|
|
while ((result = regex.exec(searchString)) !== null) {
|
|
// const matchedString = result[0];
|
|
const padding = result[1];
|
|
const truncation = result[2];
|
|
const conversionCharacter = result[3];
|
|
const specifier = result[5];
|
|
const text = result[6];
|
|
|
|
// Check if the pattern matched was just normal text
|
|
if (text) {
|
|
formattedString += text.toString();
|
|
} else {
|
|
// Create a raw replacement string based on the conversion
|
|
// character and specifier
|
|
const replacement = replaceToken(conversionCharacter, loggingEvent, specifier);
|
|
formattedString += truncateAndPad(replacement, truncation, padding);
|
|
}
|
|
searchString = searchString.substr(result.index + result[0].length);
|
|
}
|
|
return formattedString;
|
|
};
|
|
}
|
|
|
|
const layoutMakers = {
|
|
messagePassThrough () {
|
|
return messagePassThroughLayout;
|
|
},
|
|
basic () {
|
|
return basicLayout;
|
|
},
|
|
colored () {
|
|
return colouredLayout;
|
|
},
|
|
coloured () {
|
|
return colouredLayout;
|
|
},
|
|
pattern (config) {
|
|
return patternLayout(config && config.pattern, config && config.tokens);
|
|
},
|
|
dummy () {
|
|
return dummyLayout;
|
|
}
|
|
};
|
|
|
|
module.exports = {
|
|
basicLayout,
|
|
messagePassThroughLayout,
|
|
patternLayout,
|
|
colouredLayout,
|
|
coloredLayout: colouredLayout,
|
|
dummyLayout,
|
|
addLayout (name, serializerGenerator) {
|
|
layoutMakers[name] = serializerGenerator;
|
|
},
|
|
layout (name, config) {
|
|
return layoutMakers[name] && layoutMakers[name](config);
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 76 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
function padWithZeros(vNumber, width) {
|
|
var numAsString = vNumber.toString();
|
|
while (numAsString.length < width) {
|
|
numAsString = "0" + numAsString;
|
|
}
|
|
return numAsString;
|
|
}
|
|
|
|
function addZero(vNumber) {
|
|
return padWithZeros(vNumber, 2);
|
|
}
|
|
|
|
/**
|
|
* Formats the TimeOffset
|
|
* Thanks to http://www.svendtofte.com/code/date_format/
|
|
* @private
|
|
*/
|
|
function offset(timezoneOffset) {
|
|
var os = Math.abs(timezoneOffset);
|
|
var h = String(Math.floor(os / 60));
|
|
var m = String(os % 60);
|
|
if (h.length === 1) {
|
|
h = "0" + h;
|
|
}
|
|
if (m.length === 1) {
|
|
m = "0" + m;
|
|
}
|
|
return timezoneOffset < 0 ? "+" + h + m : "-" + h + m;
|
|
}
|
|
|
|
function datePart(date, displayUTC, part) {
|
|
return displayUTC ? date["getUTC" + part]() : date["get" + part]();
|
|
}
|
|
|
|
function asString(format, date) {
|
|
if (typeof format !== "string") {
|
|
date = format;
|
|
format = module.exports.ISO8601_FORMAT;
|
|
}
|
|
if (!date) {
|
|
date = module.exports.now();
|
|
}
|
|
|
|
var displayUTC = format.indexOf("O") > -1;
|
|
|
|
var vDay = addZero(datePart(date, displayUTC, "Date"));
|
|
var vMonth = addZero(datePart(date, displayUTC, "Month") + 1);
|
|
var vYearLong = addZero(datePart(date, displayUTC, "FullYear"));
|
|
var vYearShort = addZero(vYearLong.substring(2, 4));
|
|
var vYear = format.indexOf("yyyy") > -1 ? vYearLong : vYearShort;
|
|
var vHour = addZero(datePart(date, displayUTC, "Hours"));
|
|
var vMinute = addZero(datePart(date, displayUTC, "Minutes"));
|
|
var vSecond = addZero(datePart(date, displayUTC, "Seconds"));
|
|
var vMillisecond = padWithZeros(
|
|
datePart(date, displayUTC, "Milliseconds"),
|
|
3
|
|
);
|
|
var vTimeZone = offset(date.getTimezoneOffset());
|
|
var formatted = format
|
|
.replace(/dd/g, vDay)
|
|
.replace(/MM/g, vMonth)
|
|
.replace(/y{1,4}/g, vYear)
|
|
.replace(/hh/g, vHour)
|
|
.replace(/mm/g, vMinute)
|
|
.replace(/ss/g, vSecond)
|
|
.replace(/SSS/g, vMillisecond)
|
|
.replace(/O/g, vTimeZone);
|
|
return formatted;
|
|
}
|
|
|
|
function extractDateParts(pattern, str, missingValuesDate) {
|
|
var matchers = [
|
|
{
|
|
pattern: /y{1,4}/,
|
|
regexp: "\\d{1,4}",
|
|
fn: function(date, value) {
|
|
date.setFullYear(value);
|
|
}
|
|
},
|
|
{
|
|
pattern: /MM/,
|
|
regexp: "\\d{1,2}",
|
|
fn: function(date, value) {
|
|
date.setMonth(value - 1);
|
|
}
|
|
},
|
|
{
|
|
pattern: /dd/,
|
|
regexp: "\\d{1,2}",
|
|
fn: function(date, value) {
|
|
date.setDate(value);
|
|
}
|
|
},
|
|
{
|
|
pattern: /hh/,
|
|
regexp: "\\d{1,2}",
|
|
fn: function(date, value) {
|
|
date.setHours(value);
|
|
}
|
|
},
|
|
{
|
|
pattern: /mm/,
|
|
regexp: "\\d\\d",
|
|
fn: function(date, value) {
|
|
date.setMinutes(value);
|
|
}
|
|
},
|
|
{
|
|
pattern: /ss/,
|
|
regexp: "\\d\\d",
|
|
fn: function(date, value) {
|
|
date.setSeconds(value);
|
|
}
|
|
},
|
|
{
|
|
pattern: /SSS/,
|
|
regexp: "\\d\\d\\d",
|
|
fn: function(date, value) {
|
|
date.setMilliseconds(value);
|
|
}
|
|
},
|
|
{
|
|
pattern: /O/,
|
|
regexp: "[+-]\\d{3,4}|Z",
|
|
fn: function(date, value) {
|
|
if (value === "Z") {
|
|
value = 0;
|
|
}
|
|
var offset = Math.abs(value);
|
|
var minutes = (offset % 100) + Math.floor(offset / 100) * 60;
|
|
date.setMinutes(date.getMinutes() + (value > 0 ? minutes : -minutes));
|
|
}
|
|
}
|
|
];
|
|
|
|
var parsedPattern = matchers.reduce(
|
|
function(p, m) {
|
|
if (m.pattern.test(p.regexp)) {
|
|
m.index = p.regexp.match(m.pattern).index;
|
|
p.regexp = p.regexp.replace(m.pattern, "(" + m.regexp + ")");
|
|
} else {
|
|
m.index = -1;
|
|
}
|
|
return p;
|
|
},
|
|
{ regexp: pattern, index: [] }
|
|
);
|
|
|
|
var dateFns = matchers.filter(function(m) {
|
|
return m.index > -1;
|
|
});
|
|
dateFns.sort(function(a, b) {
|
|
return a.index - b.index;
|
|
});
|
|
|
|
var matcher = new RegExp(parsedPattern.regexp);
|
|
var matches = matcher.exec(str);
|
|
if (matches) {
|
|
var date = missingValuesDate || module.exports.now();
|
|
dateFns.forEach(function(f, i) {
|
|
f.fn(date, matches[i + 1]);
|
|
});
|
|
return date;
|
|
}
|
|
|
|
throw new Error(
|
|
"String '" + str + "' could not be parsed as '" + pattern + "'"
|
|
);
|
|
}
|
|
|
|
function parse(pattern, str, missingValuesDate) {
|
|
if (!pattern) {
|
|
throw new Error("pattern must be supplied");
|
|
}
|
|
|
|
return extractDateParts(pattern, str, missingValuesDate);
|
|
}
|
|
|
|
/**
|
|
* Used for testing - replace this function with a fixed date.
|
|
*/
|
|
function now() {
|
|
return new Date();
|
|
}
|
|
|
|
module.exports = asString;
|
|
module.exports.asString = asString;
|
|
module.exports.parse = parse;
|
|
module.exports.now = now;
|
|
module.exports.ISO8601_FORMAT = "yyyy-MM-ddThh:mm:ss.SSS";
|
|
module.exports.ISO8601_WITH_TZ_OFFSET_FORMAT = "yyyy-MM-ddThh:mm:ss.SSSO";
|
|
module.exports.DATETIME_FORMAT = "dd MM yyyy hh:mm:ss.SSS";
|
|
module.exports.ABSOLUTETIME_FORMAT = "hh:mm:ss.SSS";
|
|
|
|
|
|
/***/ }),
|
|
/* 77 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
|
|
|
|
const configuration = __webpack_require__(74);
|
|
|
|
const validColours = [
|
|
'white', 'grey', 'black',
|
|
'blue', 'cyan', 'green',
|
|
'magenta', 'red', 'yellow'
|
|
];
|
|
|
|
class Level {
|
|
constructor(level, levelStr, colour) {
|
|
this.level = level;
|
|
this.levelStr = levelStr;
|
|
this.colour = colour;
|
|
}
|
|
|
|
toString() {
|
|
return this.levelStr;
|
|
}
|
|
|
|
/**
|
|
* converts given String to corresponding Level
|
|
* @param {Level|String} sArg -- String value of Level OR Log4js.Level
|
|
* @param {Level} [defaultLevel] -- default Level, if no String representation
|
|
* @return {Level}
|
|
*/
|
|
static getLevel(sArg, defaultLevel) {
|
|
if (!sArg) {
|
|
return defaultLevel;
|
|
}
|
|
|
|
if (sArg instanceof Level) {
|
|
return sArg;
|
|
}
|
|
|
|
// a json-serialised level won't be an instance of Level (see issue #768)
|
|
if (sArg instanceof Object && sArg.levelStr) {
|
|
sArg = sArg.levelStr;
|
|
}
|
|
|
|
return Level[sArg.toString().toUpperCase()] || defaultLevel;
|
|
}
|
|
|
|
static addLevels(customLevels) {
|
|
if (customLevels) {
|
|
const levels = Object.keys(customLevels);
|
|
levels.forEach((l) => {
|
|
const levelStr = l.toUpperCase();
|
|
Level[levelStr] = new Level(
|
|
customLevels[l].value,
|
|
levelStr,
|
|
customLevels[l].colour
|
|
);
|
|
const existingLevelIndex = Level.levels.findIndex(lvl => lvl.levelStr === levelStr);
|
|
if (existingLevelIndex > -1) {
|
|
Level.levels[existingLevelIndex] = Level[levelStr];
|
|
} else {
|
|
Level.levels.push(Level[levelStr]);
|
|
}
|
|
});
|
|
Level.levels.sort((a, b) => a.level - b.level);
|
|
}
|
|
}
|
|
|
|
|
|
isLessThanOrEqualTo(otherLevel) {
|
|
if (typeof otherLevel === 'string') {
|
|
otherLevel = Level.getLevel(otherLevel);
|
|
}
|
|
return this.level <= otherLevel.level;
|
|
}
|
|
|
|
isGreaterThanOrEqualTo(otherLevel) {
|
|
if (typeof otherLevel === 'string') {
|
|
otherLevel = Level.getLevel(otherLevel);
|
|
}
|
|
return this.level >= otherLevel.level;
|
|
}
|
|
|
|
isEqualTo(otherLevel) {
|
|
if (typeof otherLevel === 'string') {
|
|
otherLevel = Level.getLevel(otherLevel);
|
|
}
|
|
return this.level === otherLevel.level;
|
|
}
|
|
}
|
|
|
|
Level.levels = [];
|
|
Level.addLevels({
|
|
ALL: { value: Number.MIN_VALUE, colour: 'grey' },
|
|
TRACE: { value: 5000, colour: 'blue' },
|
|
DEBUG: { value: 10000, colour: 'cyan' },
|
|
INFO: { value: 20000, colour: 'green' },
|
|
WARN: { value: 30000, colour: 'yellow' },
|
|
ERROR: { value: 40000, colour: 'red' },
|
|
FATAL: { value: 50000, colour: 'magenta' },
|
|
MARK: { value: 9007199254740992, colour: 'grey' }, // 2^53
|
|
OFF: { value: Number.MAX_VALUE, colour: 'grey' }
|
|
});
|
|
|
|
configuration.addListener((config) => {
|
|
const levelConfig = config.levels;
|
|
if (levelConfig) {
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(configuration.anObject(levelConfig)),
|
|
'levels must be an object'
|
|
);
|
|
const newLevels = Object.keys(levelConfig);
|
|
newLevels.forEach((l) => {
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(configuration.validIdentifier(l)),
|
|
`level name "${l}" is not a valid identifier (must start with a letter, only contain A-Z,a-z,0-9,_)`
|
|
);
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(configuration.anObject(levelConfig[l])),
|
|
`level "${l}" must be an object`
|
|
);
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(levelConfig[l].value),
|
|
`level "${l}" must have a 'value' property`
|
|
);
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(configuration.anInteger(levelConfig[l].value)),
|
|
`level "${l}".value must have an integer value`
|
|
);
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(levelConfig[l].colour),
|
|
`level "${l}" must have a 'colour' property`
|
|
);
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(validColours.indexOf(levelConfig[l].colour) > -1),
|
|
`level "${l}".colour must be one of ${validColours.join(', ')}`
|
|
);
|
|
});
|
|
}
|
|
});
|
|
|
|
configuration.addListener((config) => {
|
|
Level.addLevels(config.levels);
|
|
});
|
|
|
|
module.exports = Level;
|
|
|
|
|
|
/***/ }),
|
|
/* 78 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const path = __webpack_require__(57);
|
|
const debug = __webpack_require__(65)('log4js:appenders');
|
|
const configuration = __webpack_require__(74);
|
|
const clustering = __webpack_require__(79);
|
|
const levels = __webpack_require__(77);
|
|
const layouts = __webpack_require__(75);
|
|
const adapters = __webpack_require__(83);
|
|
|
|
// pre-load the core appenders so that webpack can find them
|
|
const coreAppenders = new Map();
|
|
coreAppenders.set('console', __webpack_require__(84));
|
|
coreAppenders.set('stdout', __webpack_require__(85));
|
|
coreAppenders.set('stderr', __webpack_require__(86));
|
|
coreAppenders.set('logLevelFilter', __webpack_require__(87));
|
|
coreAppenders.set('categoryFilter', __webpack_require__(88));
|
|
coreAppenders.set('noLogFilter', __webpack_require__(89));
|
|
coreAppenders.set('file', __webpack_require__(90));
|
|
coreAppenders.set('dateFile', __webpack_require__(143));
|
|
|
|
const appenders = new Map();
|
|
|
|
const tryLoading = (modulePath, config) => {
|
|
debug('Loading module from ', modulePath);
|
|
try {
|
|
return __webpack_require__(144)(modulePath); //eslint-disable-line
|
|
} catch (e) {
|
|
// if the module was found, and we still got an error, then raise it
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
e.code !== 'MODULE_NOT_FOUND',
|
|
`appender "${modulePath}" could not be loaded (error was: ${e})`
|
|
);
|
|
return undefined;
|
|
}
|
|
};
|
|
|
|
const loadAppenderModule = (type, config) => coreAppenders.get(type)
|
|
|| tryLoading(`./${type}`, config)
|
|
|| tryLoading(type, config)
|
|
|| (__webpack_require__.c[__webpack_require__.s] && tryLoading(path.join(path.dirname(__webpack_require__.c[__webpack_require__.s].filename), type), config))
|
|
|| tryLoading(path.join(process.cwd(), type), config);
|
|
|
|
const createAppender = (name, config) => {
|
|
const appenderConfig = config.appenders[name];
|
|
const appenderModule = appenderConfig.type.configure
|
|
? appenderConfig.type : loadAppenderModule(appenderConfig.type, config);
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(appenderModule),
|
|
`appender "${name}" is not valid (type "${appenderConfig.type}" could not be found)`
|
|
);
|
|
if (appenderModule.appender) {
|
|
debug(`DEPRECATION: Appender ${appenderConfig.type} exports an appender function.`);
|
|
}
|
|
if (appenderModule.shutdown) {
|
|
debug(`DEPRECATION: Appender ${appenderConfig.type} exports a shutdown function.`);
|
|
}
|
|
|
|
debug(`${name}: clustering.isMaster ? ${clustering.isMaster()}`);
|
|
debug(`${name}: appenderModule is ${__webpack_require__(40).inspect(appenderModule)}`); // eslint-disable-line
|
|
return clustering.onlyOnMaster(() => {
|
|
debug(`calling appenderModule.configure for ${name} / ${appenderConfig.type}`);
|
|
return appenderModule.configure(
|
|
adapters.modifyConfig(appenderConfig),
|
|
layouts,
|
|
appender => appenders.get(appender),
|
|
levels
|
|
);
|
|
}, () => {});
|
|
};
|
|
|
|
const setup = (config) => {
|
|
appenders.clear();
|
|
|
|
Object.keys(config.appenders).forEach((name) => {
|
|
debug(`Creating appender ${name}`);
|
|
appenders.set(name, createAppender(name, config));
|
|
});
|
|
};
|
|
|
|
setup({ appenders: { out: { type: 'stdout' } } });
|
|
|
|
configuration.addListener((config) => {
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(configuration.anObject(config.appenders)),
|
|
'must have a property "appenders" of type object.'
|
|
);
|
|
const appenderNames = Object.keys(config.appenders);
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(appenderNames.length),
|
|
'must define at least one appender.'
|
|
);
|
|
|
|
appenderNames.forEach((name) => {
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(config.appenders[name].type),
|
|
`appender "${name}" is not valid (must be an object with property "type")`
|
|
);
|
|
});
|
|
});
|
|
|
|
configuration.addListener(setup);
|
|
|
|
module.exports = appenders;
|
|
|
|
|
|
/***/ }),
|
|
/* 79 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const debug = __webpack_require__(65)("log4js:clustering");
|
|
const LoggingEvent = __webpack_require__(80);
|
|
const configuration = __webpack_require__(74);
|
|
|
|
let disabled = false;
|
|
let cluster = null;
|
|
try {
|
|
cluster = __webpack_require__(82); //eslint-disable-line
|
|
} catch (e) {
|
|
debug("cluster module not present");
|
|
disabled = true;
|
|
}
|
|
|
|
const listeners = [];
|
|
|
|
let pm2 = false;
|
|
let pm2InstanceVar = "NODE_APP_INSTANCE";
|
|
|
|
const isPM2Master = () => pm2 && process.env[pm2InstanceVar] === "0";
|
|
const isMaster = () => disabled || cluster.isMaster || isPM2Master();
|
|
|
|
const sendToListeners = logEvent => {
|
|
listeners.forEach(l => l(logEvent));
|
|
};
|
|
|
|
// in a multi-process node environment, worker loggers will use
|
|
// process.send
|
|
const receiver = (worker, message) => {
|
|
// prior to node v6, the worker parameter was not passed (args were message, handle)
|
|
debug("cluster message received from worker ", worker, ": ", message);
|
|
if (worker.topic && worker.data) {
|
|
message = worker;
|
|
worker = undefined;
|
|
}
|
|
if (message && message.topic && message.topic === "log4js:message") {
|
|
debug("received message: ", message.data);
|
|
const logEvent = LoggingEvent.deserialise(message.data);
|
|
sendToListeners(logEvent);
|
|
}
|
|
};
|
|
|
|
if (!disabled) {
|
|
configuration.addListener(config => {
|
|
// clear out the listeners, because configure has been called.
|
|
listeners.length = 0;
|
|
|
|
({
|
|
pm2,
|
|
disableClustering: disabled,
|
|
pm2InstanceVar = "NODE_APP_INSTANCE"
|
|
} = config);
|
|
|
|
debug(`clustering disabled ? ${disabled}`);
|
|
debug(`cluster.isMaster ? ${cluster && cluster.isMaster}`);
|
|
debug(`pm2 enabled ? ${pm2}`);
|
|
debug(`pm2InstanceVar = ${pm2InstanceVar}`);
|
|
debug(`process.env[${pm2InstanceVar}] = ${process.env[pm2InstanceVar]}`);
|
|
|
|
// just in case configure is called after shutdown
|
|
if (pm2) {
|
|
process.removeListener("message", receiver);
|
|
}
|
|
if (cluster && cluster.removeListener) {
|
|
cluster.removeListener("message", receiver);
|
|
}
|
|
|
|
if (disabled || config.disableClustering) {
|
|
debug("Not listening for cluster messages, because clustering disabled.");
|
|
} else if (isPM2Master()) {
|
|
// PM2 cluster support
|
|
// PM2 runs everything as workers - install pm2-intercom for this to work.
|
|
// we only want one of the app instances to write logs
|
|
debug("listening for PM2 broadcast messages");
|
|
process.on("message", receiver);
|
|
} else if (cluster.isMaster) {
|
|
debug("listening for cluster messages");
|
|
cluster.on("message", receiver);
|
|
} else {
|
|
debug("not listening for messages, because we are not a master process");
|
|
}
|
|
});
|
|
}
|
|
|
|
module.exports = {
|
|
onlyOnMaster: (fn, notMaster) => (isMaster() ? fn() : notMaster),
|
|
isMaster,
|
|
send: msg => {
|
|
if (isMaster()) {
|
|
sendToListeners(msg);
|
|
} else {
|
|
if (!pm2) {
|
|
msg.cluster = {
|
|
workerId: cluster.worker.id,
|
|
worker: process.pid
|
|
};
|
|
}
|
|
process.send({ topic: "log4js:message", data: msg.serialise() });
|
|
}
|
|
},
|
|
onMessage: listener => {
|
|
listeners.push(listener);
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 80 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const flatted = __webpack_require__(81);
|
|
const levels = __webpack_require__(77);
|
|
|
|
/**
|
|
* @name LoggingEvent
|
|
* @namespace Log4js
|
|
*/
|
|
class LoggingEvent {
|
|
/**
|
|
* Models a logging event.
|
|
* @constructor
|
|
* @param {String} categoryName name of category
|
|
* @param {Log4js.Level} level level of message
|
|
* @param {Array} data objects to log
|
|
* @author Seth Chisamore
|
|
*/
|
|
constructor(categoryName, level, data, context, location) {
|
|
this.startTime = new Date();
|
|
this.categoryName = categoryName;
|
|
this.data = data;
|
|
this.level = level;
|
|
this.context = Object.assign({}, context);
|
|
this.pid = process.pid;
|
|
|
|
if (location) {
|
|
this.functionName = location.functionName;
|
|
this.fileName = location.fileName;
|
|
this.lineNumber = location.lineNumber;
|
|
this.columnNumber = location.columnNumber;
|
|
this.callStack = location.callStack;
|
|
}
|
|
}
|
|
|
|
serialise() {
|
|
const logData = this.data.map((e) => {
|
|
// JSON.stringify(new Error('test')) returns {}, which is not really useful for us.
|
|
// The following allows us to serialize errors correctly.
|
|
if (e && e.message && e.stack) {
|
|
e = Object.assign({ message: e.message, stack: e.stack }, e);
|
|
}
|
|
return e;
|
|
});
|
|
this.data = logData;
|
|
return flatted.stringify(this);
|
|
}
|
|
|
|
static deserialise(serialised) {
|
|
let event;
|
|
try {
|
|
const rehydratedEvent = flatted.parse(serialised);
|
|
rehydratedEvent.data = rehydratedEvent.data.map((e) => {
|
|
if (e && e.message && e.stack) {
|
|
const fakeError = new Error(e);
|
|
Object.keys(e).forEach((key) => { fakeError[key] = e[key]; });
|
|
e = fakeError;
|
|
}
|
|
return e;
|
|
});
|
|
event = new LoggingEvent(
|
|
rehydratedEvent.categoryName,
|
|
levels.getLevel(rehydratedEvent.level.levelStr),
|
|
rehydratedEvent.data,
|
|
rehydratedEvent.context
|
|
);
|
|
event.startTime = new Date(rehydratedEvent.startTime);
|
|
event.pid = rehydratedEvent.pid;
|
|
event.cluster = rehydratedEvent.cluster;
|
|
} catch (e) {
|
|
event = new LoggingEvent(
|
|
'log4js',
|
|
levels.ERROR,
|
|
['Unable to parse log:', serialised, 'because: ', e]
|
|
);
|
|
}
|
|
|
|
return event;
|
|
}
|
|
}
|
|
|
|
module.exports = LoggingEvent;
|
|
|
|
|
|
/***/ }),
|
|
/* 81 */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parse", function() { return parse; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "stringify", function() { return stringify; });
|
|
var Flatted = (function (Primitive, primitive) {
|
|
|
|
/*!
|
|
* ISC License
|
|
*
|
|
* Copyright (c) 2018, Andrea Giammarchi, @WebReflection
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
var Flatted = {
|
|
|
|
parse: function parse(text, reviver) {
|
|
var input = JSON.parse(text, Primitives).map(primitives);
|
|
var value = input[0];
|
|
var $ = reviver || noop;
|
|
var tmp = typeof value === 'object' && value ?
|
|
revive(input, new Set, value, $) :
|
|
value;
|
|
return $.call({'': tmp}, '', tmp);
|
|
},
|
|
|
|
stringify: function stringify(value, replacer, space) {
|
|
for (var
|
|
firstRun,
|
|
known = new Map,
|
|
input = [],
|
|
output = [],
|
|
$ = replacer && typeof replacer === typeof input ?
|
|
function (k, v) {
|
|
if (k === '' || -1 < replacer.indexOf(k)) return v;
|
|
} :
|
|
(replacer || noop),
|
|
i = +set(known, input, $.call({'': value}, '', value)),
|
|
replace = function (key, value) {
|
|
if (firstRun) {
|
|
firstRun = !firstRun;
|
|
return value;
|
|
// this was invoking twice each root object
|
|
// return i < 1 ? value : $.call(this, key, value);
|
|
}
|
|
var after = $.call(this, key, value);
|
|
switch (typeof after) {
|
|
case 'object':
|
|
if (after === null) return after;
|
|
case primitive:
|
|
return known.get(after) || set(known, input, after);
|
|
}
|
|
return after;
|
|
};
|
|
i < input.length; i++
|
|
) {
|
|
firstRun = true;
|
|
output[i] = JSON.stringify(input[i], replace, space);
|
|
}
|
|
return '[' + output.join(',') + ']';
|
|
}
|
|
|
|
};
|
|
|
|
return Flatted;
|
|
|
|
function noop(key, value) {
|
|
return value;
|
|
}
|
|
|
|
function revive(input, parsed, output, $) {
|
|
return Object.keys(output).reduce(
|
|
function (output, key) {
|
|
var value = output[key];
|
|
if (value instanceof Primitive) {
|
|
var tmp = input[value];
|
|
if (typeof tmp === 'object' && !parsed.has(tmp)) {
|
|
parsed.add(tmp);
|
|
output[key] = $.call(output, key, revive(input, parsed, tmp, $));
|
|
} else {
|
|
output[key] = $.call(output, key, tmp);
|
|
}
|
|
} else
|
|
output[key] = $.call(output, key, value);
|
|
return output;
|
|
},
|
|
output
|
|
);
|
|
}
|
|
|
|
function set(known, input, value) {
|
|
var index = Primitive(input.push(value) - 1);
|
|
known.set(value, index);
|
|
return index;
|
|
}
|
|
|
|
// the two kinds of primitives
|
|
// 1. the real one
|
|
// 2. the wrapped one
|
|
|
|
function primitives(value) {
|
|
return value instanceof Primitive ? Primitive(value) : value;
|
|
}
|
|
|
|
function Primitives(key, value) {
|
|
return typeof value === primitive ? new Primitive(value) : value;
|
|
}
|
|
|
|
}(String, 'string'));
|
|
/* harmony default export */ __webpack_exports__["default"] = (Flatted);
|
|
var parse = Flatted.parse;
|
|
var stringify = Flatted.stringify;
|
|
|
|
|
|
/***/ }),
|
|
/* 82 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("cluster");
|
|
|
|
/***/ }),
|
|
/* 83 */
|
|
/***/ (function(module, exports) {
|
|
|
|
function maxFileSizeUnitTransform(maxLogSize) {
|
|
if (typeof maxLogSize === 'number' && Number.isInteger(maxLogSize)) {
|
|
return maxLogSize;
|
|
}
|
|
|
|
const units = {
|
|
K: 1024,
|
|
M: 1024 * 1024,
|
|
G: 1024 * 1024 * 1024,
|
|
};
|
|
const validUnit = Object.keys(units);
|
|
const unit = maxLogSize.substr(maxLogSize.length - 1).toLocaleUpperCase();
|
|
const value = maxLogSize.substring(0, maxLogSize.length - 1).trim();
|
|
|
|
if (validUnit.indexOf(unit) < 0 || !Number.isInteger(Number(value))) {
|
|
throw Error(`maxLogSize: "${maxLogSize}" is invalid`);
|
|
} else {
|
|
return value * units[unit];
|
|
}
|
|
}
|
|
|
|
function adapter(configAdapter, config) {
|
|
const newConfig = Object.assign({}, config);
|
|
Object.keys(configAdapter).forEach((key) => {
|
|
if (newConfig[key]) {
|
|
newConfig[key] = configAdapter[key](config[key]);
|
|
}
|
|
});
|
|
return newConfig;
|
|
}
|
|
|
|
function fileAppenderAdapter(config) {
|
|
const configAdapter = {
|
|
maxLogSize: maxFileSizeUnitTransform
|
|
};
|
|
return adapter(configAdapter, config);
|
|
}
|
|
|
|
const adapters = {
|
|
file: fileAppenderAdapter,
|
|
fileSync: fileAppenderAdapter
|
|
};
|
|
|
|
module.exports.modifyConfig = config => (adapters[config.type] ? adapters[config.type](config) : config);
|
|
|
|
|
|
/***/ }),
|
|
/* 84 */
|
|
/***/ (function(module, exports) {
|
|
|
|
// eslint-disable-next-line no-console
|
|
const consoleLog = console.log.bind(console);
|
|
|
|
function consoleAppender(layout, timezoneOffset) {
|
|
return (loggingEvent) => {
|
|
consoleLog(layout(loggingEvent, timezoneOffset));
|
|
};
|
|
}
|
|
|
|
function configure(config, layouts) {
|
|
let layout = layouts.colouredLayout;
|
|
if (config.layout) {
|
|
layout = layouts.layout(config.layout.type, config.layout);
|
|
}
|
|
return consoleAppender(layout, config.timezoneOffset);
|
|
}
|
|
|
|
module.exports.configure = configure;
|
|
|
|
|
|
/***/ }),
|
|
/* 85 */
|
|
/***/ (function(module, exports) {
|
|
|
|
|
|
|
|
function stdoutAppender(layout, timezoneOffset) {
|
|
return (loggingEvent) => {
|
|
process.stdout.write(`${layout(loggingEvent, timezoneOffset)}\n`);
|
|
};
|
|
}
|
|
|
|
function configure(config, layouts) {
|
|
let layout = layouts.colouredLayout;
|
|
if (config.layout) {
|
|
layout = layouts.layout(config.layout.type, config.layout);
|
|
}
|
|
return stdoutAppender(layout, config.timezoneOffset);
|
|
}
|
|
|
|
exports.configure = configure;
|
|
|
|
|
|
/***/ }),
|
|
/* 86 */
|
|
/***/ (function(module, exports) {
|
|
|
|
|
|
|
|
function stderrAppender(layout, timezoneOffset) {
|
|
return (loggingEvent) => {
|
|
process.stderr.write(`${layout(loggingEvent, timezoneOffset)}\n`);
|
|
};
|
|
}
|
|
|
|
function configure(config, layouts) {
|
|
let layout = layouts.colouredLayout;
|
|
if (config.layout) {
|
|
layout = layouts.layout(config.layout.type, config.layout);
|
|
}
|
|
return stderrAppender(layout, config.timezoneOffset);
|
|
}
|
|
|
|
module.exports.configure = configure;
|
|
|
|
|
|
/***/ }),
|
|
/* 87 */
|
|
/***/ (function(module, exports) {
|
|
|
|
function logLevelFilter(minLevelString, maxLevelString, appender, levels) {
|
|
const minLevel = levels.getLevel(minLevelString);
|
|
const maxLevel = levels.getLevel(maxLevelString, levels.FATAL);
|
|
return (logEvent) => {
|
|
const eventLevel = logEvent.level;
|
|
if (eventLevel.isGreaterThanOrEqualTo(minLevel) && eventLevel.isLessThanOrEqualTo(maxLevel)) {
|
|
appender(logEvent);
|
|
}
|
|
};
|
|
}
|
|
|
|
function configure(config, layouts, findAppender, levels) {
|
|
const appender = findAppender(config.appender);
|
|
return logLevelFilter(config.level, config.maxLevel, appender, levels);
|
|
}
|
|
|
|
module.exports.configure = configure;
|
|
|
|
|
|
/***/ }),
|
|
/* 88 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const debug = __webpack_require__(65)('log4js:categoryFilter');
|
|
|
|
function categoryFilter(excludes, appender) {
|
|
if (typeof excludes === 'string') excludes = [excludes];
|
|
return (logEvent) => {
|
|
debug(`Checking ${logEvent.categoryName} against ${excludes}`);
|
|
if (excludes.indexOf(logEvent.categoryName) === -1) {
|
|
debug('Not excluded, sending to appender');
|
|
appender(logEvent);
|
|
}
|
|
};
|
|
}
|
|
|
|
function configure(config, layouts, findAppender) {
|
|
const appender = findAppender(config.appender);
|
|
return categoryFilter(config.exclude, appender);
|
|
}
|
|
|
|
module.exports.configure = configure;
|
|
|
|
|
|
/***/ }),
|
|
/* 89 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
|
|
|
|
const debug = __webpack_require__(65)('log4js:noLogFilter');
|
|
|
|
/**
|
|
* The function removes empty or null regexp from the array
|
|
* @param {Array<string>} regexp
|
|
* @returns {Array<string>} a filtered string array with not empty or null regexp
|
|
*/
|
|
function removeNullOrEmptyRegexp(regexp) {
|
|
const filtered = regexp.filter(el => ((el != null) && (el !== '')));
|
|
return filtered;
|
|
}
|
|
|
|
/**
|
|
* Returns a function that will exclude the events in case they match
|
|
* with the regular expressions provided
|
|
* @param {string | Array<string>} filters contains the regexp that will be used for the evaluation
|
|
* @param {*} appender
|
|
* @returns {function}
|
|
*/
|
|
function noLogFilter(filters, appender) {
|
|
return (logEvent) => {
|
|
debug(`Checking data: ${logEvent.data} against filters: ${filters}`);
|
|
if (typeof filters === 'string') {
|
|
filters = [filters];
|
|
}
|
|
filters = removeNullOrEmptyRegexp(filters);
|
|
const regex = new RegExp(filters.join('|'), 'i');
|
|
if (filters.length === 0
|
|
|| logEvent.data.findIndex(value => regex.test(value)) < 0) {
|
|
debug('Not excluded, sending to appender');
|
|
appender(logEvent);
|
|
}
|
|
};
|
|
}
|
|
|
|
function configure(config, layouts, findAppender) {
|
|
const appender = findAppender(config.appender);
|
|
return noLogFilter(config.exclude, appender);
|
|
}
|
|
|
|
module.exports.configure = configure;
|
|
|
|
|
|
/***/ }),
|
|
/* 90 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const debug = __webpack_require__(65)('log4js:file');
|
|
const path = __webpack_require__(57);
|
|
const streams = __webpack_require__(91);
|
|
const os = __webpack_require__(56);
|
|
|
|
const eol = os.EOL || '\n';
|
|
|
|
function openTheStream(file, fileSize, numFiles, options) {
|
|
const stream = new streams.RollingFileStream(
|
|
file,
|
|
fileSize,
|
|
numFiles,
|
|
options
|
|
);
|
|
stream.on('error', (err) => {
|
|
console.error('log4js.fileAppender - Writing to file %s, error happened ', file, err); //eslint-disable-line
|
|
});
|
|
return stream;
|
|
}
|
|
|
|
|
|
/**
|
|
* File Appender writing the logs to a text file. Supports rolling of logs by size.
|
|
*
|
|
* @param file file log messages will be written to
|
|
* @param layout a function that takes a logEvent and returns a string
|
|
* (defaults to basicLayout).
|
|
* @param logSize - the maximum size (in bytes) for a log file,
|
|
* if not provided then logs won't be rotated.
|
|
* @param numBackups - the number of log files to keep after logSize
|
|
* has been reached (default 5)
|
|
* @param options - options to be passed to the underlying stream
|
|
* @param timezoneOffset - optional timezone offset in minutes (default system local)
|
|
*/
|
|
function fileAppender(file, layout, logSize, numBackups, options, timezoneOffset) {
|
|
file = path.normalize(file);
|
|
numBackups = numBackups === undefined ? 5 : numBackups;
|
|
// there has to be at least one backup if logSize has been specified
|
|
numBackups = numBackups === 0 ? 1 : numBackups;
|
|
|
|
debug(
|
|
'Creating file appender (',
|
|
file, ', ',
|
|
logSize, ', ',
|
|
numBackups, ', ',
|
|
options, ', ',
|
|
timezoneOffset, ')'
|
|
);
|
|
|
|
let writer = openTheStream(file, logSize, numBackups, options);
|
|
|
|
const app = function (loggingEvent) {
|
|
writer.write(layout(loggingEvent, timezoneOffset) + eol, 'utf8');
|
|
};
|
|
|
|
app.reopen = function () {
|
|
writer.end(() => { writer = openTheStream(file, logSize, numBackups, options); });
|
|
};
|
|
|
|
app.sighupHandler = function () {
|
|
debug('SIGHUP handler called.');
|
|
app.reopen();
|
|
};
|
|
|
|
app.shutdown = function (complete) {
|
|
process.removeListener('SIGHUP', app.sighupHandler);
|
|
writer.end('', 'utf-8', complete);
|
|
};
|
|
|
|
// On SIGHUP, close and reopen all files. This allows this appender to work with
|
|
// logrotate. Note that if you are using logrotate, you should not set
|
|
// `logSize`.
|
|
process.on('SIGHUP', app.sighupHandler);
|
|
|
|
return app;
|
|
}
|
|
|
|
function configure(config, layouts) {
|
|
let layout = layouts.basicLayout;
|
|
if (config.layout) {
|
|
layout = layouts.layout(config.layout.type, config.layout);
|
|
}
|
|
|
|
return fileAppender(
|
|
config.filename,
|
|
layout,
|
|
config.maxLogSize,
|
|
config.backups,
|
|
config,
|
|
config.timezoneOffset
|
|
);
|
|
}
|
|
|
|
module.exports.configure = configure;
|
|
|
|
|
|
/***/ }),
|
|
/* 91 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
module.exports = {
|
|
RollingFileWriteStream: __webpack_require__(92),
|
|
RollingFileStream: __webpack_require__(141),
|
|
DateRollingFileStream: __webpack_require__(142)
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 92 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const debug = __webpack_require__(65)("streamroller:RollingFileWriteStream");
|
|
const fs = __webpack_require__(93);
|
|
const zlib = __webpack_require__(137);
|
|
const path = __webpack_require__(57);
|
|
const newNow = __webpack_require__(138);
|
|
const format = __webpack_require__(76);
|
|
const { Writable } = __webpack_require__(41);
|
|
const fileNameFormatter = __webpack_require__(139);
|
|
const fileNameParser = __webpack_require__(140);
|
|
|
|
/**
|
|
* RollingFileWriteStream is mainly used when writing to a file rolling by date or size.
|
|
* RollingFileWriteStream inherits from stream.Writable
|
|
*/
|
|
class RollingFileWriteStream extends Writable {
|
|
/**
|
|
* Create a RollingFileWriteStream
|
|
* @constructor
|
|
* @param {string} filePath - The file path to write.
|
|
* @param {object} options - The extra options
|
|
* @param {number} options.numToKeep - The max numbers of files to keep.
|
|
* @param {number} options.maxSize - The maxSize one file can reach. Unit is Byte.
|
|
* This should be more than 1024. The default is Number.MAX_SAFE_INTEGER.
|
|
* @param {string} options.mode - The mode of the files. The default is '0644'. Refer to stream.writable for more.
|
|
* @param {string} options.flags - The default is 'a'. Refer to stream.flags for more.
|
|
* @param {boolean} options.compress - Whether to compress backup files.
|
|
* @param {boolean} options.keepFileExt - Whether to keep the file extension.
|
|
* @param {string} options.pattern - The date string pattern in the file name.
|
|
* @param {boolean} options.alwaysIncludePattern - Whether to add date to the name of the first file.
|
|
*/
|
|
constructor(filePath, options) {
|
|
debug(`constructor: creating RollingFileWriteStream. path=${filePath}`);
|
|
super(options);
|
|
this.options = this._parseOption(options);
|
|
this.fileObject = path.parse(filePath);
|
|
if (this.fileObject.dir === "") {
|
|
this.fileObject = path.parse(path.join(process.cwd(), filePath));
|
|
}
|
|
this.fileFormatter = fileNameFormatter({
|
|
file: this.fileObject,
|
|
alwaysIncludeDate: this.options.alwaysIncludePattern,
|
|
needsIndex: this.options.maxSize < Number.MAX_SAFE_INTEGER,
|
|
compress: this.options.compress,
|
|
keepFileExt: this.options.keepFileExt
|
|
});
|
|
|
|
this.fileNameParser = fileNameParser({
|
|
file: this.fileObject,
|
|
keepFileExt: this.options.keepFileExt,
|
|
pattern: this.options.pattern
|
|
});
|
|
|
|
this.state = {
|
|
currentSize: 0
|
|
};
|
|
|
|
if (this.options.pattern) {
|
|
this.state.currentDate = format(this.options.pattern, newNow());
|
|
}
|
|
|
|
this.filename = this.fileFormatter({
|
|
index: 0,
|
|
date: this.state.currentDate
|
|
});
|
|
if (["a", "a+", "as", "as+"].includes(this.options.flags)) {
|
|
this._setExistingSizeAndDate();
|
|
}
|
|
|
|
debug(
|
|
`constructor: create new file ${this.filename}, state=${JSON.stringify(
|
|
this.state
|
|
)}`
|
|
);
|
|
this._renewWriteStream();
|
|
}
|
|
|
|
_setExistingSizeAndDate() {
|
|
try {
|
|
const stats = fs.statSync(this.filename);
|
|
this.state.currentSize = stats.size;
|
|
if (this.options.pattern) {
|
|
this.state.currentDate = format(this.options.pattern, stats.birthtime);
|
|
}
|
|
} catch (e) {
|
|
//file does not exist, that's fine - move along
|
|
return;
|
|
}
|
|
}
|
|
|
|
_parseOption(rawOptions) {
|
|
const defaultOptions = {
|
|
maxSize: Number.MAX_SAFE_INTEGER,
|
|
numToKeep: Number.MAX_SAFE_INTEGER,
|
|
encoding: "utf8",
|
|
mode: parseInt("0644", 8),
|
|
flags: "a",
|
|
compress: false,
|
|
keepFileExt: false,
|
|
alwaysIncludePattern: false
|
|
};
|
|
const options = Object.assign({}, defaultOptions, rawOptions);
|
|
if (options.maxSize <= 0) {
|
|
throw new Error(`options.maxSize (${options.maxSize}) should be > 0`);
|
|
}
|
|
if (options.numToKeep <= 0) {
|
|
throw new Error(`options.numToKeep (${options.numToKeep}) should be > 0`);
|
|
}
|
|
debug(
|
|
`_parseOption: creating stream with option=${JSON.stringify(options)}`
|
|
);
|
|
return options;
|
|
}
|
|
|
|
_final(callback) {
|
|
this.currentFileStream.end("", this.options.encoding, callback);
|
|
}
|
|
|
|
_write(chunk, encoding, callback) {
|
|
this._shouldRoll().then(() => {
|
|
debug(
|
|
`_write: writing chunk. ` +
|
|
`file=${this.currentFileStream.path} ` +
|
|
`state=${JSON.stringify(this.state)} ` +
|
|
`chunk=${chunk}`
|
|
);
|
|
this.currentFileStream.write(chunk, encoding, e => {
|
|
this.state.currentSize += chunk.length;
|
|
callback(e);
|
|
});
|
|
});
|
|
}
|
|
|
|
async _shouldRoll() {
|
|
if (this._dateChanged() || this._tooBig()) {
|
|
debug(
|
|
`_shouldRoll: rolling because dateChanged? ${this._dateChanged()} or tooBig? ${this._tooBig()}`
|
|
);
|
|
await this._roll();
|
|
}
|
|
}
|
|
|
|
_dateChanged() {
|
|
return (
|
|
this.state.currentDate &&
|
|
this.state.currentDate !== format(this.options.pattern, newNow())
|
|
);
|
|
}
|
|
|
|
_tooBig() {
|
|
return this.state.currentSize >= this.options.maxSize;
|
|
}
|
|
|
|
_roll() {
|
|
debug(`_roll: closing the current stream`);
|
|
return new Promise((resolve, reject) => {
|
|
this.currentFileStream.end("", this.options.encoding, () => {
|
|
this._moveOldFiles()
|
|
.then(resolve)
|
|
.catch(reject);
|
|
});
|
|
});
|
|
}
|
|
|
|
async _moveOldFiles() {
|
|
const files = await this._getExistingFiles();
|
|
const todaysFiles = this.state.currentDate
|
|
? files.filter(f => f.date === this.state.currentDate)
|
|
: files;
|
|
for (let i = todaysFiles.length; i >= 0; i--) {
|
|
debug(`_moveOldFiles: i = ${i}`);
|
|
const sourceFilePath = this.fileFormatter({
|
|
date: this.state.currentDate,
|
|
index: i
|
|
});
|
|
const targetFilePath = this.fileFormatter({
|
|
date: this.state.currentDate,
|
|
index: i + 1
|
|
});
|
|
|
|
await moveAndMaybeCompressFile(
|
|
sourceFilePath,
|
|
targetFilePath,
|
|
this.options.compress && i === 0
|
|
);
|
|
}
|
|
|
|
this.state.currentSize = 0;
|
|
this.state.currentDate = this.state.currentDate
|
|
? format(this.options.pattern, newNow())
|
|
: null;
|
|
debug(
|
|
`_moveOldFiles: finished rolling files. state=${JSON.stringify(
|
|
this.state
|
|
)}`
|
|
);
|
|
this._renewWriteStream();
|
|
// wait for the file to be open before cleaning up old ones,
|
|
// otherwise the daysToKeep calculations can be off
|
|
await new Promise((resolve, reject) => {
|
|
this.currentFileStream.write("", "utf8", () => {
|
|
this._clean()
|
|
.then(resolve)
|
|
.catch(reject);
|
|
});
|
|
});
|
|
}
|
|
|
|
// Sorted from the oldest to the latest
|
|
async _getExistingFiles() {
|
|
const files = await fs.readdir(this.fileObject.dir).catch(() => []);
|
|
|
|
debug(`_getExistingFiles: files=${files}`);
|
|
const existingFileDetails = files
|
|
.map(n => this.fileNameParser(n))
|
|
.filter(n => n);
|
|
|
|
const getKey = n =>
|
|
(n.timestamp ? n.timestamp : newNow().getTime()) - n.index;
|
|
existingFileDetails.sort((a, b) => getKey(a) - getKey(b));
|
|
|
|
return existingFileDetails;
|
|
}
|
|
|
|
_renewWriteStream() {
|
|
fs.ensureDirSync(this.fileObject.dir);
|
|
const filePath = this.fileFormatter({
|
|
date: this.state.currentDate,
|
|
index: 0
|
|
});
|
|
const ops = {
|
|
flags: this.options.flags,
|
|
encoding: this.options.encoding,
|
|
mode: this.options.mode
|
|
};
|
|
this.currentFileStream = fs.createWriteStream(filePath, ops);
|
|
this.currentFileStream.on("error", e => {
|
|
this.emit("error", e);
|
|
});
|
|
}
|
|
|
|
async _clean() {
|
|
const existingFileDetails = await this._getExistingFiles();
|
|
debug(
|
|
`_clean: numToKeep = ${this.options.numToKeep}, existingFiles = ${existingFileDetails.length}`
|
|
);
|
|
debug("_clean: existing files are: ", existingFileDetails);
|
|
if (this._tooManyFiles(existingFileDetails.length)) {
|
|
const fileNamesToRemove = existingFileDetails
|
|
.map(f => path.format({ dir: this.fileObject.dir, base: f.filename }))
|
|
.slice(0, existingFileDetails.length - this.options.numToKeep - 1);
|
|
await deleteFiles(fileNamesToRemove);
|
|
}
|
|
}
|
|
|
|
_tooManyFiles(numFiles) {
|
|
return this.options.numToKeep > 0 && numFiles > this.options.numToKeep;
|
|
}
|
|
}
|
|
|
|
const moveAndMaybeCompressFile = async (
|
|
sourceFilePath,
|
|
targetFilePath,
|
|
needCompress
|
|
) => {
|
|
if (sourceFilePath === targetFilePath) {
|
|
debug(
|
|
`moveAndMaybeCompressFile: source and target are the same, not doing anything`
|
|
);
|
|
return;
|
|
}
|
|
try {
|
|
await fs.access(sourceFilePath, fs.constants.W_OK | fs.constants.R_OK);
|
|
|
|
debug(
|
|
`moveAndMaybeCompressFile: moving file from ${sourceFilePath} to ${targetFilePath} ${
|
|
needCompress ? "with" : "without"
|
|
} compress`
|
|
);
|
|
if (needCompress) {
|
|
await new Promise((resolve, reject) => {
|
|
fs.createReadStream(sourceFilePath)
|
|
.pipe(zlib.createGzip())
|
|
.pipe(fs.createWriteStream(targetFilePath))
|
|
.on("finish", () => {
|
|
debug(
|
|
`moveAndMaybeCompressFile: finished compressing ${targetFilePath}, deleting ${sourceFilePath}`
|
|
);
|
|
fs.unlink(sourceFilePath)
|
|
.then(resolve)
|
|
.catch(reject);
|
|
});
|
|
});
|
|
} else {
|
|
debug(
|
|
`moveAndMaybeCompressFile: deleting file=${targetFilePath}, renaming ${sourceFilePath} to ${targetFilePath}`
|
|
);
|
|
await fs.unlink(targetFilePath).catch(() => {
|
|
/* doesn't matter */
|
|
});
|
|
await fs.rename(sourceFilePath, targetFilePath);
|
|
}
|
|
} catch (e) {
|
|
debug(
|
|
`moveAndMaybeCompressFile: source file path does not exist. not moving. sourceFilePath=${sourceFilePath}`
|
|
);
|
|
}
|
|
};
|
|
|
|
const deleteFiles = fileNames => {
|
|
debug(`deleteFiles: files to delete: ${fileNames}`);
|
|
return Promise.all(fileNames.map(f => fs.unlink(f)));
|
|
};
|
|
|
|
module.exports = RollingFileWriteStream;
|
|
|
|
|
|
/***/ }),
|
|
/* 93 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = Object.assign(
|
|
{},
|
|
// Export promiseified graceful-fs:
|
|
__webpack_require__(94),
|
|
// Export extra methods:
|
|
__webpack_require__(102),
|
|
__webpack_require__(111),
|
|
__webpack_require__(114),
|
|
__webpack_require__(117),
|
|
__webpack_require__(123),
|
|
__webpack_require__(104),
|
|
__webpack_require__(132),
|
|
__webpack_require__(134),
|
|
__webpack_require__(136),
|
|
__webpack_require__(113),
|
|
__webpack_require__(115)
|
|
)
|
|
|
|
// Export fs.promises as a getter property so that we don't trigger
|
|
// ExperimentalWarning before fs.promises is actually accessed.
|
|
const fs = __webpack_require__(55)
|
|
if (Object.getOwnPropertyDescriptor(fs, 'promises')) {
|
|
Object.defineProperty(module.exports, 'promises', {
|
|
get () { return fs.promises }
|
|
})
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 94 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
// This is adapted from https://github.com/normalize/mz
|
|
// Copyright (c) 2014-2016 Jonathan Ong me@jongleberry.com and Contributors
|
|
const u = __webpack_require__(95).fromCallback
|
|
const fs = __webpack_require__(96)
|
|
|
|
const api = [
|
|
'access',
|
|
'appendFile',
|
|
'chmod',
|
|
'chown',
|
|
'close',
|
|
'copyFile',
|
|
'fchmod',
|
|
'fchown',
|
|
'fdatasync',
|
|
'fstat',
|
|
'fsync',
|
|
'ftruncate',
|
|
'futimes',
|
|
'lchown',
|
|
'lchmod',
|
|
'link',
|
|
'lstat',
|
|
'mkdir',
|
|
'mkdtemp',
|
|
'open',
|
|
'readFile',
|
|
'readdir',
|
|
'readlink',
|
|
'realpath',
|
|
'rename',
|
|
'rmdir',
|
|
'stat',
|
|
'symlink',
|
|
'truncate',
|
|
'unlink',
|
|
'utimes',
|
|
'writeFile'
|
|
].filter(key => {
|
|
// Some commands are not available on some systems. Ex:
|
|
// fs.copyFile was added in Node.js v8.5.0
|
|
// fs.mkdtemp was added in Node.js v5.10.0
|
|
// fs.lchown is not available on at least some Linux
|
|
return typeof fs[key] === 'function'
|
|
})
|
|
|
|
// Export all keys:
|
|
Object.keys(fs).forEach(key => {
|
|
if (key === 'promises') {
|
|
// fs.promises is a getter property that triggers ExperimentalWarning
|
|
// Don't re-export it here, the getter is defined in "lib/index.js"
|
|
return
|
|
}
|
|
exports[key] = fs[key]
|
|
})
|
|
|
|
// Universalify async methods:
|
|
api.forEach(method => {
|
|
exports[method] = u(fs[method])
|
|
})
|
|
|
|
// We differ from mz/fs in that we still ship the old, broken, fs.exists()
|
|
// since we are a drop-in replacement for the native module
|
|
exports.exists = function (filename, callback) {
|
|
if (typeof callback === 'function') {
|
|
return fs.exists(filename, callback)
|
|
}
|
|
return new Promise(resolve => {
|
|
return fs.exists(filename, resolve)
|
|
})
|
|
}
|
|
|
|
// fs.read() & fs.write need special treatment due to multiple callback args
|
|
|
|
exports.read = function (fd, buffer, offset, length, position, callback) {
|
|
if (typeof callback === 'function') {
|
|
return fs.read(fd, buffer, offset, length, position, callback)
|
|
}
|
|
return new Promise((resolve, reject) => {
|
|
fs.read(fd, buffer, offset, length, position, (err, bytesRead, buffer) => {
|
|
if (err) return reject(err)
|
|
resolve({ bytesRead, buffer })
|
|
})
|
|
})
|
|
}
|
|
|
|
// Function signature can be
|
|
// fs.write(fd, buffer[, offset[, length[, position]]], callback)
|
|
// OR
|
|
// fs.write(fd, string[, position[, encoding]], callback)
|
|
// We need to handle both cases, so we use ...args
|
|
exports.write = function (fd, buffer, ...args) {
|
|
if (typeof args[args.length - 1] === 'function') {
|
|
return fs.write(fd, buffer, ...args)
|
|
}
|
|
|
|
return new Promise((resolve, reject) => {
|
|
fs.write(fd, buffer, ...args, (err, bytesWritten, buffer) => {
|
|
if (err) return reject(err)
|
|
resolve({ bytesWritten, buffer })
|
|
})
|
|
})
|
|
}
|
|
|
|
// fs.realpath.native only available in Node v9.2+
|
|
if (typeof fs.realpath.native === 'function') {
|
|
exports.realpath.native = u(fs.realpath.native)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 95 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
exports.fromCallback = function (fn) {
|
|
return Object.defineProperty(function () {
|
|
if (typeof arguments[arguments.length - 1] === 'function') fn.apply(this, arguments)
|
|
else {
|
|
return new Promise((resolve, reject) => {
|
|
arguments[arguments.length] = (err, res) => {
|
|
if (err) return reject(err)
|
|
resolve(res)
|
|
}
|
|
arguments.length++
|
|
fn.apply(this, arguments)
|
|
})
|
|
}
|
|
}, 'name', { value: fn.name })
|
|
}
|
|
|
|
exports.fromPromise = function (fn) {
|
|
return Object.defineProperty(function () {
|
|
const cb = arguments[arguments.length - 1]
|
|
if (typeof cb !== 'function') return fn.apply(this, arguments)
|
|
else fn.apply(this, arguments).then(r => cb(null, r), cb)
|
|
}, 'name', { value: fn.name })
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 96 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var fs = __webpack_require__(55)
|
|
var polyfills = __webpack_require__(97)
|
|
var legacy = __webpack_require__(99)
|
|
var clone = __webpack_require__(100)
|
|
|
|
var util = __webpack_require__(40)
|
|
|
|
/* istanbul ignore next - node 0.x polyfill */
|
|
var gracefulQueue
|
|
var previousSymbol
|
|
|
|
/* istanbul ignore else - node 0.x polyfill */
|
|
if (typeof Symbol === 'function' && typeof Symbol.for === 'function') {
|
|
gracefulQueue = Symbol.for('graceful-fs.queue')
|
|
// This is used in testing by future versions
|
|
previousSymbol = Symbol.for('graceful-fs.previous')
|
|
} else {
|
|
gracefulQueue = '___graceful-fs.queue'
|
|
previousSymbol = '___graceful-fs.previous'
|
|
}
|
|
|
|
function noop () {}
|
|
|
|
var debug = noop
|
|
if (util.debuglog)
|
|
debug = util.debuglog('gfs4')
|
|
else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || ''))
|
|
debug = function() {
|
|
var m = util.format.apply(util, arguments)
|
|
m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ')
|
|
console.error(m)
|
|
}
|
|
|
|
// Once time initialization
|
|
if (!global[gracefulQueue]) {
|
|
// This queue can be shared by multiple loaded instances
|
|
var queue = []
|
|
Object.defineProperty(global, gracefulQueue, {
|
|
get: function() {
|
|
return queue
|
|
}
|
|
})
|
|
|
|
// Patch fs.close/closeSync to shared queue version, because we need
|
|
// to retry() whenever a close happens *anywhere* in the program.
|
|
// This is essential when multiple graceful-fs instances are
|
|
// in play at the same time.
|
|
fs.close = (function (fs$close) {
|
|
function close (fd, cb) {
|
|
return fs$close.call(fs, fd, function (err) {
|
|
// This function uses the graceful-fs shared queue
|
|
if (!err) {
|
|
retry()
|
|
}
|
|
|
|
if (typeof cb === 'function')
|
|
cb.apply(this, arguments)
|
|
})
|
|
}
|
|
|
|
Object.defineProperty(close, previousSymbol, {
|
|
value: fs$close
|
|
})
|
|
return close
|
|
})(fs.close)
|
|
|
|
fs.closeSync = (function (fs$closeSync) {
|
|
function closeSync (fd) {
|
|
// This function uses the graceful-fs shared queue
|
|
fs$closeSync.apply(fs, arguments)
|
|
retry()
|
|
}
|
|
|
|
Object.defineProperty(closeSync, previousSymbol, {
|
|
value: fs$closeSync
|
|
})
|
|
return closeSync
|
|
})(fs.closeSync)
|
|
|
|
if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) {
|
|
process.on('exit', function() {
|
|
debug(global[gracefulQueue])
|
|
__webpack_require__(101).equal(global[gracefulQueue].length, 0)
|
|
})
|
|
}
|
|
}
|
|
|
|
module.exports = patch(clone(fs))
|
|
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) {
|
|
module.exports = patch(fs)
|
|
fs.__patched = true;
|
|
}
|
|
|
|
function patch (fs) {
|
|
// Everything that references the open() function needs to be in here
|
|
polyfills(fs)
|
|
fs.gracefulify = patch
|
|
|
|
fs.createReadStream = createReadStream
|
|
fs.createWriteStream = createWriteStream
|
|
var fs$readFile = fs.readFile
|
|
fs.readFile = readFile
|
|
function readFile (path, options, cb) {
|
|
if (typeof options === 'function')
|
|
cb = options, options = null
|
|
|
|
return go$readFile(path, options, cb)
|
|
|
|
function go$readFile (path, options, cb) {
|
|
return fs$readFile(path, options, function (err) {
|
|
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
|
enqueue([go$readFile, [path, options, cb]])
|
|
else {
|
|
if (typeof cb === 'function')
|
|
cb.apply(this, arguments)
|
|
retry()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
var fs$writeFile = fs.writeFile
|
|
fs.writeFile = writeFile
|
|
function writeFile (path, data, options, cb) {
|
|
if (typeof options === 'function')
|
|
cb = options, options = null
|
|
|
|
return go$writeFile(path, data, options, cb)
|
|
|
|
function go$writeFile (path, data, options, cb) {
|
|
return fs$writeFile(path, data, options, function (err) {
|
|
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
|
enqueue([go$writeFile, [path, data, options, cb]])
|
|
else {
|
|
if (typeof cb === 'function')
|
|
cb.apply(this, arguments)
|
|
retry()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
var fs$appendFile = fs.appendFile
|
|
if (fs$appendFile)
|
|
fs.appendFile = appendFile
|
|
function appendFile (path, data, options, cb) {
|
|
if (typeof options === 'function')
|
|
cb = options, options = null
|
|
|
|
return go$appendFile(path, data, options, cb)
|
|
|
|
function go$appendFile (path, data, options, cb) {
|
|
return fs$appendFile(path, data, options, function (err) {
|
|
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
|
enqueue([go$appendFile, [path, data, options, cb]])
|
|
else {
|
|
if (typeof cb === 'function')
|
|
cb.apply(this, arguments)
|
|
retry()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
var fs$readdir = fs.readdir
|
|
fs.readdir = readdir
|
|
function readdir (path, options, cb) {
|
|
var args = [path]
|
|
if (typeof options !== 'function') {
|
|
args.push(options)
|
|
} else {
|
|
cb = options
|
|
}
|
|
args.push(go$readdir$cb)
|
|
|
|
return go$readdir(args)
|
|
|
|
function go$readdir$cb (err, files) {
|
|
if (files && files.sort)
|
|
files.sort()
|
|
|
|
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
|
enqueue([go$readdir, [args]])
|
|
|
|
else {
|
|
if (typeof cb === 'function')
|
|
cb.apply(this, arguments)
|
|
retry()
|
|
}
|
|
}
|
|
}
|
|
|
|
function go$readdir (args) {
|
|
return fs$readdir.apply(fs, args)
|
|
}
|
|
|
|
if (process.version.substr(0, 4) === 'v0.8') {
|
|
var legStreams = legacy(fs)
|
|
ReadStream = legStreams.ReadStream
|
|
WriteStream = legStreams.WriteStream
|
|
}
|
|
|
|
var fs$ReadStream = fs.ReadStream
|
|
if (fs$ReadStream) {
|
|
ReadStream.prototype = Object.create(fs$ReadStream.prototype)
|
|
ReadStream.prototype.open = ReadStream$open
|
|
}
|
|
|
|
var fs$WriteStream = fs.WriteStream
|
|
if (fs$WriteStream) {
|
|
WriteStream.prototype = Object.create(fs$WriteStream.prototype)
|
|
WriteStream.prototype.open = WriteStream$open
|
|
}
|
|
|
|
Object.defineProperty(fs, 'ReadStream', {
|
|
get: function () {
|
|
return ReadStream
|
|
},
|
|
set: function (val) {
|
|
ReadStream = val
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
})
|
|
Object.defineProperty(fs, 'WriteStream', {
|
|
get: function () {
|
|
return WriteStream
|
|
},
|
|
set: function (val) {
|
|
WriteStream = val
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
})
|
|
|
|
// legacy names
|
|
Object.defineProperty(fs, 'FileReadStream', {
|
|
get: function () {
|
|
return ReadStream
|
|
},
|
|
set: function (val) {
|
|
ReadStream = val
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
})
|
|
Object.defineProperty(fs, 'FileWriteStream', {
|
|
get: function () {
|
|
return WriteStream
|
|
},
|
|
set: function (val) {
|
|
WriteStream = val
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
})
|
|
|
|
function ReadStream (path, options) {
|
|
if (this instanceof ReadStream)
|
|
return fs$ReadStream.apply(this, arguments), this
|
|
else
|
|
return ReadStream.apply(Object.create(ReadStream.prototype), arguments)
|
|
}
|
|
|
|
function ReadStream$open () {
|
|
var that = this
|
|
open(that.path, that.flags, that.mode, function (err, fd) {
|
|
if (err) {
|
|
if (that.autoClose)
|
|
that.destroy()
|
|
|
|
that.emit('error', err)
|
|
} else {
|
|
that.fd = fd
|
|
that.emit('open', fd)
|
|
that.read()
|
|
}
|
|
})
|
|
}
|
|
|
|
function WriteStream (path, options) {
|
|
if (this instanceof WriteStream)
|
|
return fs$WriteStream.apply(this, arguments), this
|
|
else
|
|
return WriteStream.apply(Object.create(WriteStream.prototype), arguments)
|
|
}
|
|
|
|
function WriteStream$open () {
|
|
var that = this
|
|
open(that.path, that.flags, that.mode, function (err, fd) {
|
|
if (err) {
|
|
that.destroy()
|
|
that.emit('error', err)
|
|
} else {
|
|
that.fd = fd
|
|
that.emit('open', fd)
|
|
}
|
|
})
|
|
}
|
|
|
|
function createReadStream (path, options) {
|
|
return new fs.ReadStream(path, options)
|
|
}
|
|
|
|
function createWriteStream (path, options) {
|
|
return new fs.WriteStream(path, options)
|
|
}
|
|
|
|
var fs$open = fs.open
|
|
fs.open = open
|
|
function open (path, flags, mode, cb) {
|
|
if (typeof mode === 'function')
|
|
cb = mode, mode = null
|
|
|
|
return go$open(path, flags, mode, cb)
|
|
|
|
function go$open (path, flags, mode, cb) {
|
|
return fs$open(path, flags, mode, function (err, fd) {
|
|
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
|
enqueue([go$open, [path, flags, mode, cb]])
|
|
else {
|
|
if (typeof cb === 'function')
|
|
cb.apply(this, arguments)
|
|
retry()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
return fs
|
|
}
|
|
|
|
function enqueue (elem) {
|
|
debug('ENQUEUE', elem[0].name, elem[1])
|
|
global[gracefulQueue].push(elem)
|
|
}
|
|
|
|
function retry () {
|
|
var elem = global[gracefulQueue].shift()
|
|
if (elem) {
|
|
debug('RETRY', elem[0].name, elem[1])
|
|
elem[0].apply(null, elem[1])
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 97 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var constants = __webpack_require__(98)
|
|
|
|
var origCwd = process.cwd
|
|
var cwd = null
|
|
|
|
var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform
|
|
|
|
process.cwd = function() {
|
|
if (!cwd)
|
|
cwd = origCwd.call(process)
|
|
return cwd
|
|
}
|
|
try {
|
|
process.cwd()
|
|
} catch (er) {}
|
|
|
|
var chdir = process.chdir
|
|
process.chdir = function(d) {
|
|
cwd = null
|
|
chdir.call(process, d)
|
|
}
|
|
|
|
module.exports = patch
|
|
|
|
function patch (fs) {
|
|
// (re-)implement some things that are known busted or missing.
|
|
|
|
// lchmod, broken prior to 0.6.2
|
|
// back-port the fix here.
|
|
if (constants.hasOwnProperty('O_SYMLINK') &&
|
|
process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
|
|
patchLchmod(fs)
|
|
}
|
|
|
|
// lutimes implementation, or no-op
|
|
if (!fs.lutimes) {
|
|
patchLutimes(fs)
|
|
}
|
|
|
|
// https://github.com/isaacs/node-graceful-fs/issues/4
|
|
// Chown should not fail on einval or eperm if non-root.
|
|
// It should not fail on enosys ever, as this just indicates
|
|
// that a fs doesn't support the intended operation.
|
|
|
|
fs.chown = chownFix(fs.chown)
|
|
fs.fchown = chownFix(fs.fchown)
|
|
fs.lchown = chownFix(fs.lchown)
|
|
|
|
fs.chmod = chmodFix(fs.chmod)
|
|
fs.fchmod = chmodFix(fs.fchmod)
|
|
fs.lchmod = chmodFix(fs.lchmod)
|
|
|
|
fs.chownSync = chownFixSync(fs.chownSync)
|
|
fs.fchownSync = chownFixSync(fs.fchownSync)
|
|
fs.lchownSync = chownFixSync(fs.lchownSync)
|
|
|
|
fs.chmodSync = chmodFixSync(fs.chmodSync)
|
|
fs.fchmodSync = chmodFixSync(fs.fchmodSync)
|
|
fs.lchmodSync = chmodFixSync(fs.lchmodSync)
|
|
|
|
fs.stat = statFix(fs.stat)
|
|
fs.fstat = statFix(fs.fstat)
|
|
fs.lstat = statFix(fs.lstat)
|
|
|
|
fs.statSync = statFixSync(fs.statSync)
|
|
fs.fstatSync = statFixSync(fs.fstatSync)
|
|
fs.lstatSync = statFixSync(fs.lstatSync)
|
|
|
|
// if lchmod/lchown do not exist, then make them no-ops
|
|
if (!fs.lchmod) {
|
|
fs.lchmod = function (path, mode, cb) {
|
|
if (cb) process.nextTick(cb)
|
|
}
|
|
fs.lchmodSync = function () {}
|
|
}
|
|
if (!fs.lchown) {
|
|
fs.lchown = function (path, uid, gid, cb) {
|
|
if (cb) process.nextTick(cb)
|
|
}
|
|
fs.lchownSync = function () {}
|
|
}
|
|
|
|
// on Windows, A/V software can lock the directory, causing this
|
|
// to fail with an EACCES or EPERM if the directory contains newly
|
|
// created files. Try again on failure, for up to 60 seconds.
|
|
|
|
// Set the timeout this long because some Windows Anti-Virus, such as Parity
|
|
// bit9, may lock files for up to a minute, causing npm package install
|
|
// failures. Also, take care to yield the scheduler. Windows scheduling gives
|
|
// CPU to a busy looping process, which can cause the program causing the lock
|
|
// contention to be starved of CPU by node, so the contention doesn't resolve.
|
|
if (platform === "win32") {
|
|
fs.rename = (function (fs$rename) { return function (from, to, cb) {
|
|
var start = Date.now()
|
|
var backoff = 0;
|
|
fs$rename(from, to, function CB (er) {
|
|
if (er
|
|
&& (er.code === "EACCES" || er.code === "EPERM")
|
|
&& Date.now() - start < 60000) {
|
|
setTimeout(function() {
|
|
fs.stat(to, function (stater, st) {
|
|
if (stater && stater.code === "ENOENT")
|
|
fs$rename(from, to, CB);
|
|
else
|
|
cb(er)
|
|
})
|
|
}, backoff)
|
|
if (backoff < 100)
|
|
backoff += 10;
|
|
return;
|
|
}
|
|
if (cb) cb(er)
|
|
})
|
|
}})(fs.rename)
|
|
}
|
|
|
|
// if read() returns EAGAIN, then just try it again.
|
|
fs.read = (function (fs$read) {
|
|
function read (fd, buffer, offset, length, position, callback_) {
|
|
var callback
|
|
if (callback_ && typeof callback_ === 'function') {
|
|
var eagCounter = 0
|
|
callback = function (er, _, __) {
|
|
if (er && er.code === 'EAGAIN' && eagCounter < 10) {
|
|
eagCounter ++
|
|
return fs$read.call(fs, fd, buffer, offset, length, position, callback)
|
|
}
|
|
callback_.apply(this, arguments)
|
|
}
|
|
}
|
|
return fs$read.call(fs, fd, buffer, offset, length, position, callback)
|
|
}
|
|
|
|
// This ensures `util.promisify` works as it does for native `fs.read`.
|
|
read.__proto__ = fs$read
|
|
return read
|
|
})(fs.read)
|
|
|
|
fs.readSync = (function (fs$readSync) { return function (fd, buffer, offset, length, position) {
|
|
var eagCounter = 0
|
|
while (true) {
|
|
try {
|
|
return fs$readSync.call(fs, fd, buffer, offset, length, position)
|
|
} catch (er) {
|
|
if (er.code === 'EAGAIN' && eagCounter < 10) {
|
|
eagCounter ++
|
|
continue
|
|
}
|
|
throw er
|
|
}
|
|
}
|
|
}})(fs.readSync)
|
|
|
|
function patchLchmod (fs) {
|
|
fs.lchmod = function (path, mode, callback) {
|
|
fs.open( path
|
|
, constants.O_WRONLY | constants.O_SYMLINK
|
|
, mode
|
|
, function (err, fd) {
|
|
if (err) {
|
|
if (callback) callback(err)
|
|
return
|
|
}
|
|
// prefer to return the chmod error, if one occurs,
|
|
// but still try to close, and report closing errors if they occur.
|
|
fs.fchmod(fd, mode, function (err) {
|
|
fs.close(fd, function(err2) {
|
|
if (callback) callback(err || err2)
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
fs.lchmodSync = function (path, mode) {
|
|
var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode)
|
|
|
|
// prefer to return the chmod error, if one occurs,
|
|
// but still try to close, and report closing errors if they occur.
|
|
var threw = true
|
|
var ret
|
|
try {
|
|
ret = fs.fchmodSync(fd, mode)
|
|
threw = false
|
|
} finally {
|
|
if (threw) {
|
|
try {
|
|
fs.closeSync(fd)
|
|
} catch (er) {}
|
|
} else {
|
|
fs.closeSync(fd)
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
}
|
|
|
|
function patchLutimes (fs) {
|
|
if (constants.hasOwnProperty("O_SYMLINK")) {
|
|
fs.lutimes = function (path, at, mt, cb) {
|
|
fs.open(path, constants.O_SYMLINK, function (er, fd) {
|
|
if (er) {
|
|
if (cb) cb(er)
|
|
return
|
|
}
|
|
fs.futimes(fd, at, mt, function (er) {
|
|
fs.close(fd, function (er2) {
|
|
if (cb) cb(er || er2)
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
fs.lutimesSync = function (path, at, mt) {
|
|
var fd = fs.openSync(path, constants.O_SYMLINK)
|
|
var ret
|
|
var threw = true
|
|
try {
|
|
ret = fs.futimesSync(fd, at, mt)
|
|
threw = false
|
|
} finally {
|
|
if (threw) {
|
|
try {
|
|
fs.closeSync(fd)
|
|
} catch (er) {}
|
|
} else {
|
|
fs.closeSync(fd)
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
} else {
|
|
fs.lutimes = function (_a, _b, _c, cb) { if (cb) process.nextTick(cb) }
|
|
fs.lutimesSync = function () {}
|
|
}
|
|
}
|
|
|
|
function chmodFix (orig) {
|
|
if (!orig) return orig
|
|
return function (target, mode, cb) {
|
|
return orig.call(fs, target, mode, function (er) {
|
|
if (chownErOk(er)) er = null
|
|
if (cb) cb.apply(this, arguments)
|
|
})
|
|
}
|
|
}
|
|
|
|
function chmodFixSync (orig) {
|
|
if (!orig) return orig
|
|
return function (target, mode) {
|
|
try {
|
|
return orig.call(fs, target, mode)
|
|
} catch (er) {
|
|
if (!chownErOk(er)) throw er
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function chownFix (orig) {
|
|
if (!orig) return orig
|
|
return function (target, uid, gid, cb) {
|
|
return orig.call(fs, target, uid, gid, function (er) {
|
|
if (chownErOk(er)) er = null
|
|
if (cb) cb.apply(this, arguments)
|
|
})
|
|
}
|
|
}
|
|
|
|
function chownFixSync (orig) {
|
|
if (!orig) return orig
|
|
return function (target, uid, gid) {
|
|
try {
|
|
return orig.call(fs, target, uid, gid)
|
|
} catch (er) {
|
|
if (!chownErOk(er)) throw er
|
|
}
|
|
}
|
|
}
|
|
|
|
function statFix (orig) {
|
|
if (!orig) return orig
|
|
// Older versions of Node erroneously returned signed integers for
|
|
// uid + gid.
|
|
return function (target, options, cb) {
|
|
if (typeof options === 'function') {
|
|
cb = options
|
|
options = null
|
|
}
|
|
function callback (er, stats) {
|
|
if (stats) {
|
|
if (stats.uid < 0) stats.uid += 0x100000000
|
|
if (stats.gid < 0) stats.gid += 0x100000000
|
|
}
|
|
if (cb) cb.apply(this, arguments)
|
|
}
|
|
return options ? orig.call(fs, target, options, callback)
|
|
: orig.call(fs, target, callback)
|
|
}
|
|
}
|
|
|
|
function statFixSync (orig) {
|
|
if (!orig) return orig
|
|
// Older versions of Node erroneously returned signed integers for
|
|
// uid + gid.
|
|
return function (target, options) {
|
|
var stats = options ? orig.call(fs, target, options)
|
|
: orig.call(fs, target)
|
|
if (stats.uid < 0) stats.uid += 0x100000000
|
|
if (stats.gid < 0) stats.gid += 0x100000000
|
|
return stats;
|
|
}
|
|
}
|
|
|
|
// ENOSYS means that the fs doesn't support the op. Just ignore
|
|
// that, because it doesn't matter.
|
|
//
|
|
// if there's no getuid, or if getuid() is something other
|
|
// than 0, and the error is EINVAL or EPERM, then just ignore
|
|
// it.
|
|
//
|
|
// This specific case is a silent failure in cp, install, tar,
|
|
// and most other unix tools that manage permissions.
|
|
//
|
|
// When running as root, or if other types of errors are
|
|
// encountered, then it's strict.
|
|
function chownErOk (er) {
|
|
if (!er)
|
|
return true
|
|
|
|
if (er.code === "ENOSYS")
|
|
return true
|
|
|
|
var nonroot = !process.getuid || process.getuid() !== 0
|
|
if (nonroot) {
|
|
if (er.code === "EINVAL" || er.code === "EPERM")
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 98 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("constants");
|
|
|
|
/***/ }),
|
|
/* 99 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var Stream = __webpack_require__(41).Stream
|
|
|
|
module.exports = legacy
|
|
|
|
function legacy (fs) {
|
|
return {
|
|
ReadStream: ReadStream,
|
|
WriteStream: WriteStream
|
|
}
|
|
|
|
function ReadStream (path, options) {
|
|
if (!(this instanceof ReadStream)) return new ReadStream(path, options);
|
|
|
|
Stream.call(this);
|
|
|
|
var self = this;
|
|
|
|
this.path = path;
|
|
this.fd = null;
|
|
this.readable = true;
|
|
this.paused = false;
|
|
|
|
this.flags = 'r';
|
|
this.mode = 438; /*=0666*/
|
|
this.bufferSize = 64 * 1024;
|
|
|
|
options = options || {};
|
|
|
|
// Mixin options into this
|
|
var keys = Object.keys(options);
|
|
for (var index = 0, length = keys.length; index < length; index++) {
|
|
var key = keys[index];
|
|
this[key] = options[key];
|
|
}
|
|
|
|
if (this.encoding) this.setEncoding(this.encoding);
|
|
|
|
if (this.start !== undefined) {
|
|
if ('number' !== typeof this.start) {
|
|
throw TypeError('start must be a Number');
|
|
}
|
|
if (this.end === undefined) {
|
|
this.end = Infinity;
|
|
} else if ('number' !== typeof this.end) {
|
|
throw TypeError('end must be a Number');
|
|
}
|
|
|
|
if (this.start > this.end) {
|
|
throw new Error('start must be <= end');
|
|
}
|
|
|
|
this.pos = this.start;
|
|
}
|
|
|
|
if (this.fd !== null) {
|
|
process.nextTick(function() {
|
|
self._read();
|
|
});
|
|
return;
|
|
}
|
|
|
|
fs.open(this.path, this.flags, this.mode, function (err, fd) {
|
|
if (err) {
|
|
self.emit('error', err);
|
|
self.readable = false;
|
|
return;
|
|
}
|
|
|
|
self.fd = fd;
|
|
self.emit('open', fd);
|
|
self._read();
|
|
})
|
|
}
|
|
|
|
function WriteStream (path, options) {
|
|
if (!(this instanceof WriteStream)) return new WriteStream(path, options);
|
|
|
|
Stream.call(this);
|
|
|
|
this.path = path;
|
|
this.fd = null;
|
|
this.writable = true;
|
|
|
|
this.flags = 'w';
|
|
this.encoding = 'binary';
|
|
this.mode = 438; /*=0666*/
|
|
this.bytesWritten = 0;
|
|
|
|
options = options || {};
|
|
|
|
// Mixin options into this
|
|
var keys = Object.keys(options);
|
|
for (var index = 0, length = keys.length; index < length; index++) {
|
|
var key = keys[index];
|
|
this[key] = options[key];
|
|
}
|
|
|
|
if (this.start !== undefined) {
|
|
if ('number' !== typeof this.start) {
|
|
throw TypeError('start must be a Number');
|
|
}
|
|
if (this.start < 0) {
|
|
throw new Error('start must be >= zero');
|
|
}
|
|
|
|
this.pos = this.start;
|
|
}
|
|
|
|
this.busy = false;
|
|
this._queue = [];
|
|
|
|
if (this.fd === null) {
|
|
this._open = fs.open;
|
|
this._queue.push([this._open, this.path, this.flags, this.mode, undefined]);
|
|
this.flush();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 100 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = clone
|
|
|
|
function clone (obj) {
|
|
if (obj === null || typeof obj !== 'object')
|
|
return obj
|
|
|
|
if (obj instanceof Object)
|
|
var copy = { __proto__: obj.__proto__ }
|
|
else
|
|
var copy = Object.create(null)
|
|
|
|
Object.getOwnPropertyNames(obj).forEach(function (key) {
|
|
Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key))
|
|
})
|
|
|
|
return copy
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 101 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("assert");
|
|
|
|
/***/ }),
|
|
/* 102 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = {
|
|
copySync: __webpack_require__(103)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 103 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const fs = __webpack_require__(96)
|
|
const path = __webpack_require__(57)
|
|
const mkdirpSync = __webpack_require__(104).mkdirsSync
|
|
const utimesSync = __webpack_require__(108).utimesMillisSync
|
|
const stat = __webpack_require__(109)
|
|
|
|
function copySync (src, dest, opts) {
|
|
if (typeof opts === 'function') {
|
|
opts = { filter: opts }
|
|
}
|
|
|
|
opts = opts || {}
|
|
opts.clobber = 'clobber' in opts ? !!opts.clobber : true // default to true for now
|
|
opts.overwrite = 'overwrite' in opts ? !!opts.overwrite : opts.clobber // overwrite falls back to clobber
|
|
|
|
// Warn about using preserveTimestamps on 32-bit node
|
|
if (opts.preserveTimestamps && process.arch === 'ia32') {
|
|
console.warn(`fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended;\n
|
|
see https://github.com/jprichardson/node-fs-extra/issues/269`)
|
|
}
|
|
|
|
const { srcStat, destStat } = stat.checkPathsSync(src, dest, 'copy')
|
|
stat.checkParentPathsSync(src, srcStat, dest, 'copy')
|
|
return handleFilterAndCopy(destStat, src, dest, opts)
|
|
}
|
|
|
|
function handleFilterAndCopy (destStat, src, dest, opts) {
|
|
if (opts.filter && !opts.filter(src, dest)) return
|
|
const destParent = path.dirname(dest)
|
|
if (!fs.existsSync(destParent)) mkdirpSync(destParent)
|
|
return startCopy(destStat, src, dest, opts)
|
|
}
|
|
|
|
function startCopy (destStat, src, dest, opts) {
|
|
if (opts.filter && !opts.filter(src, dest)) return
|
|
return getStats(destStat, src, dest, opts)
|
|
}
|
|
|
|
function getStats (destStat, src, dest, opts) {
|
|
const statSync = opts.dereference ? fs.statSync : fs.lstatSync
|
|
const srcStat = statSync(src)
|
|
|
|
if (srcStat.isDirectory()) return onDir(srcStat, destStat, src, dest, opts)
|
|
else if (srcStat.isFile() ||
|
|
srcStat.isCharacterDevice() ||
|
|
srcStat.isBlockDevice()) return onFile(srcStat, destStat, src, dest, opts)
|
|
else if (srcStat.isSymbolicLink()) return onLink(destStat, src, dest, opts)
|
|
}
|
|
|
|
function onFile (srcStat, destStat, src, dest, opts) {
|
|
if (!destStat) return copyFile(srcStat, src, dest, opts)
|
|
return mayCopyFile(srcStat, src, dest, opts)
|
|
}
|
|
|
|
function mayCopyFile (srcStat, src, dest, opts) {
|
|
if (opts.overwrite) {
|
|
fs.unlinkSync(dest)
|
|
return copyFile(srcStat, src, dest, opts)
|
|
} else if (opts.errorOnExist) {
|
|
throw new Error(`'${dest}' already exists`)
|
|
}
|
|
}
|
|
|
|
function copyFile (srcStat, src, dest, opts) {
|
|
if (typeof fs.copyFileSync === 'function') {
|
|
fs.copyFileSync(src, dest)
|
|
fs.chmodSync(dest, srcStat.mode)
|
|
if (opts.preserveTimestamps) {
|
|
return utimesSync(dest, srcStat.atime, srcStat.mtime)
|
|
}
|
|
return
|
|
}
|
|
return copyFileFallback(srcStat, src, dest, opts)
|
|
}
|
|
|
|
function copyFileFallback (srcStat, src, dest, opts) {
|
|
const BUF_LENGTH = 64 * 1024
|
|
const _buff = __webpack_require__(110)(BUF_LENGTH)
|
|
|
|
const fdr = fs.openSync(src, 'r')
|
|
const fdw = fs.openSync(dest, 'w', srcStat.mode)
|
|
let pos = 0
|
|
|
|
while (pos < srcStat.size) {
|
|
const bytesRead = fs.readSync(fdr, _buff, 0, BUF_LENGTH, pos)
|
|
fs.writeSync(fdw, _buff, 0, bytesRead)
|
|
pos += bytesRead
|
|
}
|
|
|
|
if (opts.preserveTimestamps) fs.futimesSync(fdw, srcStat.atime, srcStat.mtime)
|
|
|
|
fs.closeSync(fdr)
|
|
fs.closeSync(fdw)
|
|
}
|
|
|
|
function onDir (srcStat, destStat, src, dest, opts) {
|
|
if (!destStat) return mkDirAndCopy(srcStat, src, dest, opts)
|
|
if (destStat && !destStat.isDirectory()) {
|
|
throw new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`)
|
|
}
|
|
return copyDir(src, dest, opts)
|
|
}
|
|
|
|
function mkDirAndCopy (srcStat, src, dest, opts) {
|
|
fs.mkdirSync(dest)
|
|
copyDir(src, dest, opts)
|
|
return fs.chmodSync(dest, srcStat.mode)
|
|
}
|
|
|
|
function copyDir (src, dest, opts) {
|
|
fs.readdirSync(src).forEach(item => copyDirItem(item, src, dest, opts))
|
|
}
|
|
|
|
function copyDirItem (item, src, dest, opts) {
|
|
const srcItem = path.join(src, item)
|
|
const destItem = path.join(dest, item)
|
|
const { destStat } = stat.checkPathsSync(srcItem, destItem, 'copy')
|
|
return startCopy(destStat, srcItem, destItem, opts)
|
|
}
|
|
|
|
function onLink (destStat, src, dest, opts) {
|
|
let resolvedSrc = fs.readlinkSync(src)
|
|
if (opts.dereference) {
|
|
resolvedSrc = path.resolve(process.cwd(), resolvedSrc)
|
|
}
|
|
|
|
if (!destStat) {
|
|
return fs.symlinkSync(resolvedSrc, dest)
|
|
} else {
|
|
let resolvedDest
|
|
try {
|
|
resolvedDest = fs.readlinkSync(dest)
|
|
} catch (err) {
|
|
// dest exists and is a regular file or directory,
|
|
// Windows may throw UNKNOWN error. If dest already exists,
|
|
// fs throws error anyway, so no need to guard against it here.
|
|
if (err.code === 'EINVAL' || err.code === 'UNKNOWN') return fs.symlinkSync(resolvedSrc, dest)
|
|
throw err
|
|
}
|
|
if (opts.dereference) {
|
|
resolvedDest = path.resolve(process.cwd(), resolvedDest)
|
|
}
|
|
if (stat.isSrcSubdir(resolvedSrc, resolvedDest)) {
|
|
throw new Error(`Cannot copy '${resolvedSrc}' to a subdirectory of itself, '${resolvedDest}'.`)
|
|
}
|
|
|
|
// prevent copy if src is a subdir of dest since unlinking
|
|
// dest in this case would result in removing src contents
|
|
// and therefore a broken symlink would be created.
|
|
if (fs.statSync(dest).isDirectory() && stat.isSrcSubdir(resolvedDest, resolvedSrc)) {
|
|
throw new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`)
|
|
}
|
|
return copyLink(resolvedSrc, dest)
|
|
}
|
|
}
|
|
|
|
function copyLink (resolvedSrc, dest) {
|
|
fs.unlinkSync(dest)
|
|
return fs.symlinkSync(resolvedSrc, dest)
|
|
}
|
|
|
|
module.exports = copySync
|
|
|
|
|
|
/***/ }),
|
|
/* 104 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
const u = __webpack_require__(95).fromCallback
|
|
const mkdirs = u(__webpack_require__(105))
|
|
const mkdirsSync = __webpack_require__(107)
|
|
|
|
module.exports = {
|
|
mkdirs,
|
|
mkdirsSync,
|
|
// alias
|
|
mkdirp: mkdirs,
|
|
mkdirpSync: mkdirsSync,
|
|
ensureDir: mkdirs,
|
|
ensureDirSync: mkdirsSync
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 105 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const fs = __webpack_require__(96)
|
|
const path = __webpack_require__(57)
|
|
const invalidWin32Path = __webpack_require__(106).invalidWin32Path
|
|
|
|
const o777 = parseInt('0777', 8)
|
|
|
|
function mkdirs (p, opts, callback, made) {
|
|
if (typeof opts === 'function') {
|
|
callback = opts
|
|
opts = {}
|
|
} else if (!opts || typeof opts !== 'object') {
|
|
opts = { mode: opts }
|
|
}
|
|
|
|
if (process.platform === 'win32' && invalidWin32Path(p)) {
|
|
const errInval = new Error(p + ' contains invalid WIN32 path characters.')
|
|
errInval.code = 'EINVAL'
|
|
return callback(errInval)
|
|
}
|
|
|
|
let mode = opts.mode
|
|
const xfs = opts.fs || fs
|
|
|
|
if (mode === undefined) {
|
|
mode = o777 & (~process.umask())
|
|
}
|
|
if (!made) made = null
|
|
|
|
callback = callback || function () {}
|
|
p = path.resolve(p)
|
|
|
|
xfs.mkdir(p, mode, er => {
|
|
if (!er) {
|
|
made = made || p
|
|
return callback(null, made)
|
|
}
|
|
switch (er.code) {
|
|
case 'ENOENT':
|
|
if (path.dirname(p) === p) return callback(er)
|
|
mkdirs(path.dirname(p), opts, (er, made) => {
|
|
if (er) callback(er, made)
|
|
else mkdirs(p, opts, callback, made)
|
|
})
|
|
break
|
|
|
|
// In the case of any other error, just see if there's a dir
|
|
// there already. If so, then hooray! If not, then something
|
|
// is borked.
|
|
default:
|
|
xfs.stat(p, (er2, stat) => {
|
|
// if the stat fails, then that's super weird.
|
|
// let the original error be the failure reason.
|
|
if (er2 || !stat.isDirectory()) callback(er, made)
|
|
else callback(null, made)
|
|
})
|
|
break
|
|
}
|
|
})
|
|
}
|
|
|
|
module.exports = mkdirs
|
|
|
|
|
|
/***/ }),
|
|
/* 106 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const path = __webpack_require__(57)
|
|
|
|
// get drive on windows
|
|
function getRootPath (p) {
|
|
p = path.normalize(path.resolve(p)).split(path.sep)
|
|
if (p.length > 0) return p[0]
|
|
return null
|
|
}
|
|
|
|
// http://stackoverflow.com/a/62888/10333 contains more accurate
|
|
// TODO: expand to include the rest
|
|
const INVALID_PATH_CHARS = /[<>:"|?*]/
|
|
|
|
function invalidWin32Path (p) {
|
|
const rp = getRootPath(p)
|
|
p = p.replace(rp, '')
|
|
return INVALID_PATH_CHARS.test(p)
|
|
}
|
|
|
|
module.exports = {
|
|
getRootPath,
|
|
invalidWin32Path
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 107 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const fs = __webpack_require__(96)
|
|
const path = __webpack_require__(57)
|
|
const invalidWin32Path = __webpack_require__(106).invalidWin32Path
|
|
|
|
const o777 = parseInt('0777', 8)
|
|
|
|
function mkdirsSync (p, opts, made) {
|
|
if (!opts || typeof opts !== 'object') {
|
|
opts = { mode: opts }
|
|
}
|
|
|
|
let mode = opts.mode
|
|
const xfs = opts.fs || fs
|
|
|
|
if (process.platform === 'win32' && invalidWin32Path(p)) {
|
|
const errInval = new Error(p + ' contains invalid WIN32 path characters.')
|
|
errInval.code = 'EINVAL'
|
|
throw errInval
|
|
}
|
|
|
|
if (mode === undefined) {
|
|
mode = o777 & (~process.umask())
|
|
}
|
|
if (!made) made = null
|
|
|
|
p = path.resolve(p)
|
|
|
|
try {
|
|
xfs.mkdirSync(p, mode)
|
|
made = made || p
|
|
} catch (err0) {
|
|
if (err0.code === 'ENOENT') {
|
|
if (path.dirname(p) === p) throw err0
|
|
made = mkdirsSync(path.dirname(p), opts, made)
|
|
mkdirsSync(p, opts, made)
|
|
} else {
|
|
// In the case of any other error, just see if there's a dir there
|
|
// already. If so, then hooray! If not, then something is borked.
|
|
let stat
|
|
try {
|
|
stat = xfs.statSync(p)
|
|
} catch (err1) {
|
|
throw err0
|
|
}
|
|
if (!stat.isDirectory()) throw err0
|
|
}
|
|
}
|
|
|
|
return made
|
|
}
|
|
|
|
module.exports = mkdirsSync
|
|
|
|
|
|
/***/ }),
|
|
/* 108 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const fs = __webpack_require__(96)
|
|
const os = __webpack_require__(56)
|
|
const path = __webpack_require__(57)
|
|
|
|
// HFS, ext{2,3}, FAT do not, Node.js v0.10 does not
|
|
function hasMillisResSync () {
|
|
let tmpfile = path.join('millis-test-sync' + Date.now().toString() + Math.random().toString().slice(2))
|
|
tmpfile = path.join(os.tmpdir(), tmpfile)
|
|
|
|
// 550 millis past UNIX epoch
|
|
const d = new Date(1435410243862)
|
|
fs.writeFileSync(tmpfile, 'https://github.com/jprichardson/node-fs-extra/pull/141')
|
|
const fd = fs.openSync(tmpfile, 'r+')
|
|
fs.futimesSync(fd, d, d)
|
|
fs.closeSync(fd)
|
|
return fs.statSync(tmpfile).mtime > 1435410243000
|
|
}
|
|
|
|
function hasMillisRes (callback) {
|
|
let tmpfile = path.join('millis-test' + Date.now().toString() + Math.random().toString().slice(2))
|
|
tmpfile = path.join(os.tmpdir(), tmpfile)
|
|
|
|
// 550 millis past UNIX epoch
|
|
const d = new Date(1435410243862)
|
|
fs.writeFile(tmpfile, 'https://github.com/jprichardson/node-fs-extra/pull/141', err => {
|
|
if (err) return callback(err)
|
|
fs.open(tmpfile, 'r+', (err, fd) => {
|
|
if (err) return callback(err)
|
|
fs.futimes(fd, d, d, err => {
|
|
if (err) return callback(err)
|
|
fs.close(fd, err => {
|
|
if (err) return callback(err)
|
|
fs.stat(tmpfile, (err, stats) => {
|
|
if (err) return callback(err)
|
|
callback(null, stats.mtime > 1435410243000)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
function timeRemoveMillis (timestamp) {
|
|
if (typeof timestamp === 'number') {
|
|
return Math.floor(timestamp / 1000) * 1000
|
|
} else if (timestamp instanceof Date) {
|
|
return new Date(Math.floor(timestamp.getTime() / 1000) * 1000)
|
|
} else {
|
|
throw new Error('fs-extra: timeRemoveMillis() unknown parameter type')
|
|
}
|
|
}
|
|
|
|
function utimesMillis (path, atime, mtime, callback) {
|
|
// if (!HAS_MILLIS_RES) return fs.utimes(path, atime, mtime, callback)
|
|
fs.open(path, 'r+', (err, fd) => {
|
|
if (err) return callback(err)
|
|
fs.futimes(fd, atime, mtime, futimesErr => {
|
|
fs.close(fd, closeErr => {
|
|
if (callback) callback(futimesErr || closeErr)
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
function utimesMillisSync (path, atime, mtime) {
|
|
const fd = fs.openSync(path, 'r+')
|
|
fs.futimesSync(fd, atime, mtime)
|
|
return fs.closeSync(fd)
|
|
}
|
|
|
|
module.exports = {
|
|
hasMillisRes,
|
|
hasMillisResSync,
|
|
timeRemoveMillis,
|
|
utimesMillis,
|
|
utimesMillisSync
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 109 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const fs = __webpack_require__(96)
|
|
const path = __webpack_require__(57)
|
|
|
|
const NODE_VERSION_MAJOR_WITH_BIGINT = 10
|
|
const NODE_VERSION_MINOR_WITH_BIGINT = 5
|
|
const NODE_VERSION_PATCH_WITH_BIGINT = 0
|
|
const nodeVersion = process.versions.node.split('.')
|
|
const nodeVersionMajor = Number.parseInt(nodeVersion[0], 10)
|
|
const nodeVersionMinor = Number.parseInt(nodeVersion[1], 10)
|
|
const nodeVersionPatch = Number.parseInt(nodeVersion[2], 10)
|
|
|
|
function nodeSupportsBigInt () {
|
|
if (nodeVersionMajor > NODE_VERSION_MAJOR_WITH_BIGINT) {
|
|
return true
|
|
} else if (nodeVersionMajor === NODE_VERSION_MAJOR_WITH_BIGINT) {
|
|
if (nodeVersionMinor > NODE_VERSION_MINOR_WITH_BIGINT) {
|
|
return true
|
|
} else if (nodeVersionMinor === NODE_VERSION_MINOR_WITH_BIGINT) {
|
|
if (nodeVersionPatch >= NODE_VERSION_PATCH_WITH_BIGINT) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
function getStats (src, dest, cb) {
|
|
if (nodeSupportsBigInt()) {
|
|
fs.stat(src, { bigint: true }, (err, srcStat) => {
|
|
if (err) return cb(err)
|
|
fs.stat(dest, { bigint: true }, (err, destStat) => {
|
|
if (err) {
|
|
if (err.code === 'ENOENT') return cb(null, { srcStat, destStat: null })
|
|
return cb(err)
|
|
}
|
|
return cb(null, { srcStat, destStat })
|
|
})
|
|
})
|
|
} else {
|
|
fs.stat(src, (err, srcStat) => {
|
|
if (err) return cb(err)
|
|
fs.stat(dest, (err, destStat) => {
|
|
if (err) {
|
|
if (err.code === 'ENOENT') return cb(null, { srcStat, destStat: null })
|
|
return cb(err)
|
|
}
|
|
return cb(null, { srcStat, destStat })
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
function getStatsSync (src, dest) {
|
|
let srcStat, destStat
|
|
if (nodeSupportsBigInt()) {
|
|
srcStat = fs.statSync(src, { bigint: true })
|
|
} else {
|
|
srcStat = fs.statSync(src)
|
|
}
|
|
try {
|
|
if (nodeSupportsBigInt()) {
|
|
destStat = fs.statSync(dest, { bigint: true })
|
|
} else {
|
|
destStat = fs.statSync(dest)
|
|
}
|
|
} catch (err) {
|
|
if (err.code === 'ENOENT') return { srcStat, destStat: null }
|
|
throw err
|
|
}
|
|
return { srcStat, destStat }
|
|
}
|
|
|
|
function checkPaths (src, dest, funcName, cb) {
|
|
getStats(src, dest, (err, stats) => {
|
|
if (err) return cb(err)
|
|
const { srcStat, destStat } = stats
|
|
if (destStat && destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
|
|
return cb(new Error('Source and destination must not be the same.'))
|
|
}
|
|
if (srcStat.isDirectory() && isSrcSubdir(src, dest)) {
|
|
return cb(new Error(errMsg(src, dest, funcName)))
|
|
}
|
|
return cb(null, { srcStat, destStat })
|
|
})
|
|
}
|
|
|
|
function checkPathsSync (src, dest, funcName) {
|
|
const { srcStat, destStat } = getStatsSync(src, dest)
|
|
if (destStat && destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
|
|
throw new Error('Source and destination must not be the same.')
|
|
}
|
|
if (srcStat.isDirectory() && isSrcSubdir(src, dest)) {
|
|
throw new Error(errMsg(src, dest, funcName))
|
|
}
|
|
return { srcStat, destStat }
|
|
}
|
|
|
|
// recursively check if dest parent is a subdirectory of src.
|
|
// It works for all file types including symlinks since it
|
|
// checks the src and dest inodes. It starts from the deepest
|
|
// parent and stops once it reaches the src parent or the root path.
|
|
function checkParentPaths (src, srcStat, dest, funcName, cb) {
|
|
const srcParent = path.resolve(path.dirname(src))
|
|
const destParent = path.resolve(path.dirname(dest))
|
|
if (destParent === srcParent || destParent === path.parse(destParent).root) return cb()
|
|
if (nodeSupportsBigInt()) {
|
|
fs.stat(destParent, { bigint: true }, (err, destStat) => {
|
|
if (err) {
|
|
if (err.code === 'ENOENT') return cb()
|
|
return cb(err)
|
|
}
|
|
if (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
|
|
return cb(new Error(errMsg(src, dest, funcName)))
|
|
}
|
|
return checkParentPaths(src, srcStat, destParent, funcName, cb)
|
|
})
|
|
} else {
|
|
fs.stat(destParent, (err, destStat) => {
|
|
if (err) {
|
|
if (err.code === 'ENOENT') return cb()
|
|
return cb(err)
|
|
}
|
|
if (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
|
|
return cb(new Error(errMsg(src, dest, funcName)))
|
|
}
|
|
return checkParentPaths(src, srcStat, destParent, funcName, cb)
|
|
})
|
|
}
|
|
}
|
|
|
|
function checkParentPathsSync (src, srcStat, dest, funcName) {
|
|
const srcParent = path.resolve(path.dirname(src))
|
|
const destParent = path.resolve(path.dirname(dest))
|
|
if (destParent === srcParent || destParent === path.parse(destParent).root) return
|
|
let destStat
|
|
try {
|
|
if (nodeSupportsBigInt()) {
|
|
destStat = fs.statSync(destParent, { bigint: true })
|
|
} else {
|
|
destStat = fs.statSync(destParent)
|
|
}
|
|
} catch (err) {
|
|
if (err.code === 'ENOENT') return
|
|
throw err
|
|
}
|
|
if (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
|
|
throw new Error(errMsg(src, dest, funcName))
|
|
}
|
|
return checkParentPathsSync(src, srcStat, destParent, funcName)
|
|
}
|
|
|
|
// return true if dest is a subdir of src, otherwise false.
|
|
// It only checks the path strings.
|
|
function isSrcSubdir (src, dest) {
|
|
const srcArr = path.resolve(src).split(path.sep).filter(i => i)
|
|
const destArr = path.resolve(dest).split(path.sep).filter(i => i)
|
|
return srcArr.reduce((acc, cur, i) => acc && destArr[i] === cur, true)
|
|
}
|
|
|
|
function errMsg (src, dest, funcName) {
|
|
return `Cannot ${funcName} '${src}' to a subdirectory of itself, '${dest}'.`
|
|
}
|
|
|
|
module.exports = {
|
|
checkPaths,
|
|
checkPathsSync,
|
|
checkParentPaths,
|
|
checkParentPathsSync,
|
|
isSrcSubdir
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 110 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
/* eslint-disable node/no-deprecated-api */
|
|
module.exports = function (size) {
|
|
if (typeof Buffer.allocUnsafe === 'function') {
|
|
try {
|
|
return Buffer.allocUnsafe(size)
|
|
} catch (e) {
|
|
return new Buffer(size)
|
|
}
|
|
}
|
|
return new Buffer(size)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 111 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const u = __webpack_require__(95).fromCallback
|
|
module.exports = {
|
|
copy: u(__webpack_require__(112))
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 112 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const fs = __webpack_require__(96)
|
|
const path = __webpack_require__(57)
|
|
const mkdirp = __webpack_require__(104).mkdirs
|
|
const pathExists = __webpack_require__(113).pathExists
|
|
const utimes = __webpack_require__(108).utimesMillis
|
|
const stat = __webpack_require__(109)
|
|
|
|
function copy (src, dest, opts, cb) {
|
|
if (typeof opts === 'function' && !cb) {
|
|
cb = opts
|
|
opts = {}
|
|
} else if (typeof opts === 'function') {
|
|
opts = { filter: opts }
|
|
}
|
|
|
|
cb = cb || function () {}
|
|
opts = opts || {}
|
|
|
|
opts.clobber = 'clobber' in opts ? !!opts.clobber : true // default to true for now
|
|
opts.overwrite = 'overwrite' in opts ? !!opts.overwrite : opts.clobber // overwrite falls back to clobber
|
|
|
|
// Warn about using preserveTimestamps on 32-bit node
|
|
if (opts.preserveTimestamps && process.arch === 'ia32') {
|
|
console.warn(`fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended;\n
|
|
see https://github.com/jprichardson/node-fs-extra/issues/269`)
|
|
}
|
|
|
|
stat.checkPaths(src, dest, 'copy', (err, stats) => {
|
|
if (err) return cb(err)
|
|
const { srcStat, destStat } = stats
|
|
stat.checkParentPaths(src, srcStat, dest, 'copy', err => {
|
|
if (err) return cb(err)
|
|
if (opts.filter) return handleFilter(checkParentDir, destStat, src, dest, opts, cb)
|
|
return checkParentDir(destStat, src, dest, opts, cb)
|
|
})
|
|
})
|
|
}
|
|
|
|
function checkParentDir (destStat, src, dest, opts, cb) {
|
|
const destParent = path.dirname(dest)
|
|
pathExists(destParent, (err, dirExists) => {
|
|
if (err) return cb(err)
|
|
if (dirExists) return startCopy(destStat, src, dest, opts, cb)
|
|
mkdirp(destParent, err => {
|
|
if (err) return cb(err)
|
|
return startCopy(destStat, src, dest, opts, cb)
|
|
})
|
|
})
|
|
}
|
|
|
|
function handleFilter (onInclude, destStat, src, dest, opts, cb) {
|
|
Promise.resolve(opts.filter(src, dest)).then(include => {
|
|
if (include) return onInclude(destStat, src, dest, opts, cb)
|
|
return cb()
|
|
}, error => cb(error))
|
|
}
|
|
|
|
function startCopy (destStat, src, dest, opts, cb) {
|
|
if (opts.filter) return handleFilter(getStats, destStat, src, dest, opts, cb)
|
|
return getStats(destStat, src, dest, opts, cb)
|
|
}
|
|
|
|
function getStats (destStat, src, dest, opts, cb) {
|
|
const stat = opts.dereference ? fs.stat : fs.lstat
|
|
stat(src, (err, srcStat) => {
|
|
if (err) return cb(err)
|
|
|
|
if (srcStat.isDirectory()) return onDir(srcStat, destStat, src, dest, opts, cb)
|
|
else if (srcStat.isFile() ||
|
|
srcStat.isCharacterDevice() ||
|
|
srcStat.isBlockDevice()) return onFile(srcStat, destStat, src, dest, opts, cb)
|
|
else if (srcStat.isSymbolicLink()) return onLink(destStat, src, dest, opts, cb)
|
|
})
|
|
}
|
|
|
|
function onFile (srcStat, destStat, src, dest, opts, cb) {
|
|
if (!destStat) return copyFile(srcStat, src, dest, opts, cb)
|
|
return mayCopyFile(srcStat, src, dest, opts, cb)
|
|
}
|
|
|
|
function mayCopyFile (srcStat, src, dest, opts, cb) {
|
|
if (opts.overwrite) {
|
|
fs.unlink(dest, err => {
|
|
if (err) return cb(err)
|
|
return copyFile(srcStat, src, dest, opts, cb)
|
|
})
|
|
} else if (opts.errorOnExist) {
|
|
return cb(new Error(`'${dest}' already exists`))
|
|
} else return cb()
|
|
}
|
|
|
|
function copyFile (srcStat, src, dest, opts, cb) {
|
|
if (typeof fs.copyFile === 'function') {
|
|
return fs.copyFile(src, dest, err => {
|
|
if (err) return cb(err)
|
|
return setDestModeAndTimestamps(srcStat, dest, opts, cb)
|
|
})
|
|
}
|
|
return copyFileFallback(srcStat, src, dest, opts, cb)
|
|
}
|
|
|
|
function copyFileFallback (srcStat, src, dest, opts, cb) {
|
|
const rs = fs.createReadStream(src)
|
|
rs.on('error', err => cb(err)).once('open', () => {
|
|
const ws = fs.createWriteStream(dest, { mode: srcStat.mode })
|
|
ws.on('error', err => cb(err))
|
|
.on('open', () => rs.pipe(ws))
|
|
.once('close', () => setDestModeAndTimestamps(srcStat, dest, opts, cb))
|
|
})
|
|
}
|
|
|
|
function setDestModeAndTimestamps (srcStat, dest, opts, cb) {
|
|
fs.chmod(dest, srcStat.mode, err => {
|
|
if (err) return cb(err)
|
|
if (opts.preserveTimestamps) {
|
|
return utimes(dest, srcStat.atime, srcStat.mtime, cb)
|
|
}
|
|
return cb()
|
|
})
|
|
}
|
|
|
|
function onDir (srcStat, destStat, src, dest, opts, cb) {
|
|
if (!destStat) return mkDirAndCopy(srcStat, src, dest, opts, cb)
|
|
if (destStat && !destStat.isDirectory()) {
|
|
return cb(new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`))
|
|
}
|
|
return copyDir(src, dest, opts, cb)
|
|
}
|
|
|
|
function mkDirAndCopy (srcStat, src, dest, opts, cb) {
|
|
fs.mkdir(dest, err => {
|
|
if (err) return cb(err)
|
|
copyDir(src, dest, opts, err => {
|
|
if (err) return cb(err)
|
|
return fs.chmod(dest, srcStat.mode, cb)
|
|
})
|
|
})
|
|
}
|
|
|
|
function copyDir (src, dest, opts, cb) {
|
|
fs.readdir(src, (err, items) => {
|
|
if (err) return cb(err)
|
|
return copyDirItems(items, src, dest, opts, cb)
|
|
})
|
|
}
|
|
|
|
function copyDirItems (items, src, dest, opts, cb) {
|
|
const item = items.pop()
|
|
if (!item) return cb()
|
|
return copyDirItem(items, item, src, dest, opts, cb)
|
|
}
|
|
|
|
function copyDirItem (items, item, src, dest, opts, cb) {
|
|
const srcItem = path.join(src, item)
|
|
const destItem = path.join(dest, item)
|
|
stat.checkPaths(srcItem, destItem, 'copy', (err, stats) => {
|
|
if (err) return cb(err)
|
|
const { destStat } = stats
|
|
startCopy(destStat, srcItem, destItem, opts, err => {
|
|
if (err) return cb(err)
|
|
return copyDirItems(items, src, dest, opts, cb)
|
|
})
|
|
})
|
|
}
|
|
|
|
function onLink (destStat, src, dest, opts, cb) {
|
|
fs.readlink(src, (err, resolvedSrc) => {
|
|
if (err) return cb(err)
|
|
if (opts.dereference) {
|
|
resolvedSrc = path.resolve(process.cwd(), resolvedSrc)
|
|
}
|
|
|
|
if (!destStat) {
|
|
return fs.symlink(resolvedSrc, dest, cb)
|
|
} else {
|
|
fs.readlink(dest, (err, resolvedDest) => {
|
|
if (err) {
|
|
// dest exists and is a regular file or directory,
|
|
// Windows may throw UNKNOWN error. If dest already exists,
|
|
// fs throws error anyway, so no need to guard against it here.
|
|
if (err.code === 'EINVAL' || err.code === 'UNKNOWN') return fs.symlink(resolvedSrc, dest, cb)
|
|
return cb(err)
|
|
}
|
|
if (opts.dereference) {
|
|
resolvedDest = path.resolve(process.cwd(), resolvedDest)
|
|
}
|
|
if (stat.isSrcSubdir(resolvedSrc, resolvedDest)) {
|
|
return cb(new Error(`Cannot copy '${resolvedSrc}' to a subdirectory of itself, '${resolvedDest}'.`))
|
|
}
|
|
|
|
// do not copy if src is a subdir of dest since unlinking
|
|
// dest in this case would result in removing src contents
|
|
// and therefore a broken symlink would be created.
|
|
if (destStat.isDirectory() && stat.isSrcSubdir(resolvedDest, resolvedSrc)) {
|
|
return cb(new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`))
|
|
}
|
|
return copyLink(resolvedSrc, dest, cb)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
function copyLink (resolvedSrc, dest, cb) {
|
|
fs.unlink(dest, err => {
|
|
if (err) return cb(err)
|
|
return fs.symlink(resolvedSrc, dest, cb)
|
|
})
|
|
}
|
|
|
|
module.exports = copy
|
|
|
|
|
|
/***/ }),
|
|
/* 113 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
const u = __webpack_require__(95).fromPromise
|
|
const fs = __webpack_require__(94)
|
|
|
|
function pathExists (path) {
|
|
return fs.access(path).then(() => true).catch(() => false)
|
|
}
|
|
|
|
module.exports = {
|
|
pathExists: u(pathExists),
|
|
pathExistsSync: fs.existsSync
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 114 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const u = __webpack_require__(95).fromCallback
|
|
const fs = __webpack_require__(96)
|
|
const path = __webpack_require__(57)
|
|
const mkdir = __webpack_require__(104)
|
|
const remove = __webpack_require__(115)
|
|
|
|
const emptyDir = u(function emptyDir (dir, callback) {
|
|
callback = callback || function () {}
|
|
fs.readdir(dir, (err, items) => {
|
|
if (err) return mkdir.mkdirs(dir, callback)
|
|
|
|
items = items.map(item => path.join(dir, item))
|
|
|
|
deleteItem()
|
|
|
|
function deleteItem () {
|
|
const item = items.pop()
|
|
if (!item) return callback()
|
|
remove.remove(item, err => {
|
|
if (err) return callback(err)
|
|
deleteItem()
|
|
})
|
|
}
|
|
})
|
|
})
|
|
|
|
function emptyDirSync (dir) {
|
|
let items
|
|
try {
|
|
items = fs.readdirSync(dir)
|
|
} catch (err) {
|
|
return mkdir.mkdirsSync(dir)
|
|
}
|
|
|
|
items.forEach(item => {
|
|
item = path.join(dir, item)
|
|
remove.removeSync(item)
|
|
})
|
|
}
|
|
|
|
module.exports = {
|
|
emptyDirSync,
|
|
emptydirSync: emptyDirSync,
|
|
emptyDir,
|
|
emptydir: emptyDir
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 115 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const u = __webpack_require__(95).fromCallback
|
|
const rimraf = __webpack_require__(116)
|
|
|
|
module.exports = {
|
|
remove: u(rimraf),
|
|
removeSync: rimraf.sync
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 116 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const fs = __webpack_require__(96)
|
|
const path = __webpack_require__(57)
|
|
const assert = __webpack_require__(101)
|
|
|
|
const isWindows = (process.platform === 'win32')
|
|
|
|
function defaults (options) {
|
|
const methods = [
|
|
'unlink',
|
|
'chmod',
|
|
'stat',
|
|
'lstat',
|
|
'rmdir',
|
|
'readdir'
|
|
]
|
|
methods.forEach(m => {
|
|
options[m] = options[m] || fs[m]
|
|
m = m + 'Sync'
|
|
options[m] = options[m] || fs[m]
|
|
})
|
|
|
|
options.maxBusyTries = options.maxBusyTries || 3
|
|
}
|
|
|
|
function rimraf (p, options, cb) {
|
|
let busyTries = 0
|
|
|
|
if (typeof options === 'function') {
|
|
cb = options
|
|
options = {}
|
|
}
|
|
|
|
assert(p, 'rimraf: missing path')
|
|
assert.strictEqual(typeof p, 'string', 'rimraf: path should be a string')
|
|
assert.strictEqual(typeof cb, 'function', 'rimraf: callback function required')
|
|
assert(options, 'rimraf: invalid options argument provided')
|
|
assert.strictEqual(typeof options, 'object', 'rimraf: options should be object')
|
|
|
|
defaults(options)
|
|
|
|
rimraf_(p, options, function CB (er) {
|
|
if (er) {
|
|
if ((er.code === 'EBUSY' || er.code === 'ENOTEMPTY' || er.code === 'EPERM') &&
|
|
busyTries < options.maxBusyTries) {
|
|
busyTries++
|
|
const time = busyTries * 100
|
|
// try again, with the same exact callback as this one.
|
|
return setTimeout(() => rimraf_(p, options, CB), time)
|
|
}
|
|
|
|
// already gone
|
|
if (er.code === 'ENOENT') er = null
|
|
}
|
|
|
|
cb(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, (er, st) => {
|
|
if (er && er.code === 'ENOENT') {
|
|
return cb(null)
|
|
}
|
|
|
|
// Windows can EPERM on stat. Life is suffering.
|
|
if (er && er.code === 'EPERM' && isWindows) {
|
|
return fixWinEPERM(p, options, er, cb)
|
|
}
|
|
|
|
if (st && st.isDirectory()) {
|
|
return rmdir(p, options, er, cb)
|
|
}
|
|
|
|
options.unlink(p, 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, 0o666, er2 => {
|
|
if (er2) {
|
|
cb(er2.code === 'ENOENT' ? null : er)
|
|
} else {
|
|
options.stat(p, (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) {
|
|
let stats
|
|
|
|
assert(p)
|
|
assert(options)
|
|
if (er) {
|
|
assert(er instanceof Error)
|
|
}
|
|
|
|
try {
|
|
options.chmodSync(p, 0o666)
|
|
} catch (er2) {
|
|
if (er2.code === 'ENOENT') {
|
|
return
|
|
} else {
|
|
throw er
|
|
}
|
|
}
|
|
|
|
try {
|
|
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, 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, (er, files) => {
|
|
if (er) return cb(er)
|
|
|
|
let n = files.length
|
|
let errState
|
|
|
|
if (n === 0) return options.rmdir(p, cb)
|
|
|
|
files.forEach(f => {
|
|
rimraf(path.join(p, f), options, 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) {
|
|
let st
|
|
|
|
options = options || {}
|
|
defaults(options)
|
|
|
|
assert(p, 'rimraf: missing path')
|
|
assert.strictEqual(typeof p, 'string', 'rimraf: path should be a string')
|
|
assert(options, 'rimraf: missing options')
|
|
assert.strictEqual(typeof options, 'object', 'rimraf: options should be object')
|
|
|
|
try {
|
|
st = options.lstatSync(p)
|
|
} catch (er) {
|
|
if (er.code === 'ENOENT') {
|
|
return
|
|
}
|
|
|
|
// Windows can EPERM on stat. Life is suffering.
|
|
if (er.code === 'EPERM' && isWindows) {
|
|
fixWinEPERMSync(p, options, er)
|
|
}
|
|
}
|
|
|
|
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
|
|
} else if (er.code === 'EPERM') {
|
|
return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er)
|
|
} else if (er.code !== 'EISDIR') {
|
|
throw er
|
|
}
|
|
rmdirSync(p, options, er)
|
|
}
|
|
}
|
|
|
|
function rmdirSync (p, options, originalEr) {
|
|
assert(p)
|
|
assert(options)
|
|
if (originalEr) {
|
|
assert(originalEr instanceof Error)
|
|
}
|
|
|
|
try {
|
|
options.rmdirSync(p)
|
|
} catch (er) {
|
|
if (er.code === 'ENOTDIR') {
|
|
throw originalEr
|
|
} else if (er.code === 'ENOTEMPTY' || er.code === 'EEXIST' || er.code === 'EPERM') {
|
|
rmkidsSync(p, options)
|
|
} else if (er.code !== 'ENOENT') {
|
|
throw er
|
|
}
|
|
}
|
|
}
|
|
|
|
function rmkidsSync (p, options) {
|
|
assert(p)
|
|
assert(options)
|
|
options.readdirSync(p).forEach(f => rimrafSync(path.join(p, f), options))
|
|
|
|
if (isWindows) {
|
|
// We only end up here once we got ENOTEMPTY at least once, and
|
|
// at this point, we are guaranteed to have removed all the kids.
|
|
// So, we know that it won't be ENOENT or ENOTDIR or anything else.
|
|
// try really hard to delete stuff on windows, because it has a
|
|
// PROFOUNDLY annoying habit of not closing handles promptly when
|
|
// files are deleted, resulting in spurious ENOTEMPTY errors.
|
|
const startTime = Date.now()
|
|
do {
|
|
try {
|
|
const ret = options.rmdirSync(p, options)
|
|
return ret
|
|
} catch (er) { }
|
|
} while (Date.now() - startTime < 500) // give up after 500ms
|
|
} else {
|
|
const ret = options.rmdirSync(p, options)
|
|
return ret
|
|
}
|
|
}
|
|
|
|
module.exports = rimraf
|
|
rimraf.sync = rimrafSync
|
|
|
|
|
|
/***/ }),
|
|
/* 117 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const file = __webpack_require__(118)
|
|
const link = __webpack_require__(119)
|
|
const symlink = __webpack_require__(120)
|
|
|
|
module.exports = {
|
|
// file
|
|
createFile: file.createFile,
|
|
createFileSync: file.createFileSync,
|
|
ensureFile: file.createFile,
|
|
ensureFileSync: file.createFileSync,
|
|
// link
|
|
createLink: link.createLink,
|
|
createLinkSync: link.createLinkSync,
|
|
ensureLink: link.createLink,
|
|
ensureLinkSync: link.createLinkSync,
|
|
// symlink
|
|
createSymlink: symlink.createSymlink,
|
|
createSymlinkSync: symlink.createSymlinkSync,
|
|
ensureSymlink: symlink.createSymlink,
|
|
ensureSymlinkSync: symlink.createSymlinkSync
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 118 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const u = __webpack_require__(95).fromCallback
|
|
const path = __webpack_require__(57)
|
|
const fs = __webpack_require__(96)
|
|
const mkdir = __webpack_require__(104)
|
|
const pathExists = __webpack_require__(113).pathExists
|
|
|
|
function createFile (file, callback) {
|
|
function makeFile () {
|
|
fs.writeFile(file, '', err => {
|
|
if (err) return callback(err)
|
|
callback()
|
|
})
|
|
}
|
|
|
|
fs.stat(file, (err, stats) => { // eslint-disable-line handle-callback-err
|
|
if (!err && stats.isFile()) return callback()
|
|
const dir = path.dirname(file)
|
|
pathExists(dir, (err, dirExists) => {
|
|
if (err) return callback(err)
|
|
if (dirExists) return makeFile()
|
|
mkdir.mkdirs(dir, err => {
|
|
if (err) return callback(err)
|
|
makeFile()
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
function createFileSync (file) {
|
|
let stats
|
|
try {
|
|
stats = fs.statSync(file)
|
|
} catch (e) {}
|
|
if (stats && stats.isFile()) return
|
|
|
|
const dir = path.dirname(file)
|
|
if (!fs.existsSync(dir)) {
|
|
mkdir.mkdirsSync(dir)
|
|
}
|
|
|
|
fs.writeFileSync(file, '')
|
|
}
|
|
|
|
module.exports = {
|
|
createFile: u(createFile),
|
|
createFileSync
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 119 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const u = __webpack_require__(95).fromCallback
|
|
const path = __webpack_require__(57)
|
|
const fs = __webpack_require__(96)
|
|
const mkdir = __webpack_require__(104)
|
|
const pathExists = __webpack_require__(113).pathExists
|
|
|
|
function createLink (srcpath, dstpath, callback) {
|
|
function makeLink (srcpath, dstpath) {
|
|
fs.link(srcpath, dstpath, err => {
|
|
if (err) return callback(err)
|
|
callback(null)
|
|
})
|
|
}
|
|
|
|
pathExists(dstpath, (err, destinationExists) => {
|
|
if (err) return callback(err)
|
|
if (destinationExists) return callback(null)
|
|
fs.lstat(srcpath, (err) => {
|
|
if (err) {
|
|
err.message = err.message.replace('lstat', 'ensureLink')
|
|
return callback(err)
|
|
}
|
|
|
|
const dir = path.dirname(dstpath)
|
|
pathExists(dir, (err, dirExists) => {
|
|
if (err) return callback(err)
|
|
if (dirExists) return makeLink(srcpath, dstpath)
|
|
mkdir.mkdirs(dir, err => {
|
|
if (err) return callback(err)
|
|
makeLink(srcpath, dstpath)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
function createLinkSync (srcpath, dstpath) {
|
|
const destinationExists = fs.existsSync(dstpath)
|
|
if (destinationExists) return undefined
|
|
|
|
try {
|
|
fs.lstatSync(srcpath)
|
|
} catch (err) {
|
|
err.message = err.message.replace('lstat', 'ensureLink')
|
|
throw err
|
|
}
|
|
|
|
const dir = path.dirname(dstpath)
|
|
const dirExists = fs.existsSync(dir)
|
|
if (dirExists) return fs.linkSync(srcpath, dstpath)
|
|
mkdir.mkdirsSync(dir)
|
|
|
|
return fs.linkSync(srcpath, dstpath)
|
|
}
|
|
|
|
module.exports = {
|
|
createLink: u(createLink),
|
|
createLinkSync
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 120 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const u = __webpack_require__(95).fromCallback
|
|
const path = __webpack_require__(57)
|
|
const fs = __webpack_require__(96)
|
|
const _mkdirs = __webpack_require__(104)
|
|
const mkdirs = _mkdirs.mkdirs
|
|
const mkdirsSync = _mkdirs.mkdirsSync
|
|
|
|
const _symlinkPaths = __webpack_require__(121)
|
|
const symlinkPaths = _symlinkPaths.symlinkPaths
|
|
const symlinkPathsSync = _symlinkPaths.symlinkPathsSync
|
|
|
|
const _symlinkType = __webpack_require__(122)
|
|
const symlinkType = _symlinkType.symlinkType
|
|
const symlinkTypeSync = _symlinkType.symlinkTypeSync
|
|
|
|
const pathExists = __webpack_require__(113).pathExists
|
|
|
|
function createSymlink (srcpath, dstpath, type, callback) {
|
|
callback = (typeof type === 'function') ? type : callback
|
|
type = (typeof type === 'function') ? false : type
|
|
|
|
pathExists(dstpath, (err, destinationExists) => {
|
|
if (err) return callback(err)
|
|
if (destinationExists) return callback(null)
|
|
symlinkPaths(srcpath, dstpath, (err, relative) => {
|
|
if (err) return callback(err)
|
|
srcpath = relative.toDst
|
|
symlinkType(relative.toCwd, type, (err, type) => {
|
|
if (err) return callback(err)
|
|
const dir = path.dirname(dstpath)
|
|
pathExists(dir, (err, dirExists) => {
|
|
if (err) return callback(err)
|
|
if (dirExists) return fs.symlink(srcpath, dstpath, type, callback)
|
|
mkdirs(dir, err => {
|
|
if (err) return callback(err)
|
|
fs.symlink(srcpath, dstpath, type, callback)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
function createSymlinkSync (srcpath, dstpath, type) {
|
|
const destinationExists = fs.existsSync(dstpath)
|
|
if (destinationExists) return undefined
|
|
|
|
const relative = symlinkPathsSync(srcpath, dstpath)
|
|
srcpath = relative.toDst
|
|
type = symlinkTypeSync(relative.toCwd, type)
|
|
const dir = path.dirname(dstpath)
|
|
const exists = fs.existsSync(dir)
|
|
if (exists) return fs.symlinkSync(srcpath, dstpath, type)
|
|
mkdirsSync(dir)
|
|
return fs.symlinkSync(srcpath, dstpath, type)
|
|
}
|
|
|
|
module.exports = {
|
|
createSymlink: u(createSymlink),
|
|
createSymlinkSync
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 121 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const path = __webpack_require__(57)
|
|
const fs = __webpack_require__(96)
|
|
const pathExists = __webpack_require__(113).pathExists
|
|
|
|
/**
|
|
* Function that returns two types of paths, one relative to symlink, and one
|
|
* relative to the current working directory. Checks if path is absolute or
|
|
* relative. If the path is relative, this function checks if the path is
|
|
* relative to symlink or relative to current working directory. This is an
|
|
* initiative to find a smarter `srcpath` to supply when building symlinks.
|
|
* This allows you to determine which path to use out of one of three possible
|
|
* types of source paths. The first is an absolute path. This is detected by
|
|
* `path.isAbsolute()`. When an absolute path is provided, it is checked to
|
|
* see if it exists. If it does it's used, if not an error is returned
|
|
* (callback)/ thrown (sync). The other two options for `srcpath` are a
|
|
* relative url. By default Node's `fs.symlink` works by creating a symlink
|
|
* using `dstpath` and expects the `srcpath` to be relative to the newly
|
|
* created symlink. If you provide a `srcpath` that does not exist on the file
|
|
* system it results in a broken symlink. To minimize this, the function
|
|
* checks to see if the 'relative to symlink' source file exists, and if it
|
|
* does it will use it. If it does not, it checks if there's a file that
|
|
* exists that is relative to the current working directory, if does its used.
|
|
* This preserves the expectations of the original fs.symlink spec and adds
|
|
* the ability to pass in `relative to current working direcotry` paths.
|
|
*/
|
|
|
|
function symlinkPaths (srcpath, dstpath, callback) {
|
|
if (path.isAbsolute(srcpath)) {
|
|
return fs.lstat(srcpath, (err) => {
|
|
if (err) {
|
|
err.message = err.message.replace('lstat', 'ensureSymlink')
|
|
return callback(err)
|
|
}
|
|
return callback(null, {
|
|
'toCwd': srcpath,
|
|
'toDst': srcpath
|
|
})
|
|
})
|
|
} else {
|
|
const dstdir = path.dirname(dstpath)
|
|
const relativeToDst = path.join(dstdir, srcpath)
|
|
return pathExists(relativeToDst, (err, exists) => {
|
|
if (err) return callback(err)
|
|
if (exists) {
|
|
return callback(null, {
|
|
'toCwd': relativeToDst,
|
|
'toDst': srcpath
|
|
})
|
|
} else {
|
|
return fs.lstat(srcpath, (err) => {
|
|
if (err) {
|
|
err.message = err.message.replace('lstat', 'ensureSymlink')
|
|
return callback(err)
|
|
}
|
|
return callback(null, {
|
|
'toCwd': srcpath,
|
|
'toDst': path.relative(dstdir, srcpath)
|
|
})
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
function symlinkPathsSync (srcpath, dstpath) {
|
|
let exists
|
|
if (path.isAbsolute(srcpath)) {
|
|
exists = fs.existsSync(srcpath)
|
|
if (!exists) throw new Error('absolute srcpath does not exist')
|
|
return {
|
|
'toCwd': srcpath,
|
|
'toDst': srcpath
|
|
}
|
|
} else {
|
|
const dstdir = path.dirname(dstpath)
|
|
const relativeToDst = path.join(dstdir, srcpath)
|
|
exists = fs.existsSync(relativeToDst)
|
|
if (exists) {
|
|
return {
|
|
'toCwd': relativeToDst,
|
|
'toDst': srcpath
|
|
}
|
|
} else {
|
|
exists = fs.existsSync(srcpath)
|
|
if (!exists) throw new Error('relative srcpath does not exist')
|
|
return {
|
|
'toCwd': srcpath,
|
|
'toDst': path.relative(dstdir, srcpath)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
symlinkPaths,
|
|
symlinkPathsSync
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 122 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const fs = __webpack_require__(96)
|
|
|
|
function symlinkType (srcpath, type, callback) {
|
|
callback = (typeof type === 'function') ? type : callback
|
|
type = (typeof type === 'function') ? false : type
|
|
if (type) return callback(null, type)
|
|
fs.lstat(srcpath, (err, stats) => {
|
|
if (err) return callback(null, 'file')
|
|
type = (stats && stats.isDirectory()) ? 'dir' : 'file'
|
|
callback(null, type)
|
|
})
|
|
}
|
|
|
|
function symlinkTypeSync (srcpath, type) {
|
|
let stats
|
|
|
|
if (type) return type
|
|
try {
|
|
stats = fs.lstatSync(srcpath)
|
|
} catch (e) {
|
|
return 'file'
|
|
}
|
|
return (stats && stats.isDirectory()) ? 'dir' : 'file'
|
|
}
|
|
|
|
module.exports = {
|
|
symlinkType,
|
|
symlinkTypeSync
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 123 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const u = __webpack_require__(95).fromCallback
|
|
const jsonFile = __webpack_require__(124)
|
|
|
|
jsonFile.outputJson = u(__webpack_require__(130))
|
|
jsonFile.outputJsonSync = __webpack_require__(131)
|
|
// aliases
|
|
jsonFile.outputJSON = jsonFile.outputJson
|
|
jsonFile.outputJSONSync = jsonFile.outputJsonSync
|
|
jsonFile.writeJSON = jsonFile.writeJson
|
|
jsonFile.writeJSONSync = jsonFile.writeJsonSync
|
|
jsonFile.readJSON = jsonFile.readJson
|
|
jsonFile.readJSONSync = jsonFile.readJsonSync
|
|
|
|
module.exports = jsonFile
|
|
|
|
|
|
/***/ }),
|
|
/* 124 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const u = __webpack_require__(95).fromCallback
|
|
const jsonFile = __webpack_require__(125)
|
|
|
|
module.exports = {
|
|
// jsonfile exports
|
|
readJson: u(jsonFile.readFile),
|
|
readJsonSync: jsonFile.readFileSync,
|
|
writeJson: u(jsonFile.writeFile),
|
|
writeJsonSync: jsonFile.writeFileSync
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 125 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var _fs
|
|
try {
|
|
_fs = __webpack_require__(126)
|
|
} catch (_) {
|
|
_fs = __webpack_require__(55)
|
|
}
|
|
|
|
function readFile (file, options, callback) {
|
|
if (callback == null) {
|
|
callback = options
|
|
options = {}
|
|
}
|
|
|
|
if (typeof options === 'string') {
|
|
options = {encoding: options}
|
|
}
|
|
|
|
options = options || {}
|
|
var fs = options.fs || _fs
|
|
|
|
var shouldThrow = true
|
|
if ('throws' in options) {
|
|
shouldThrow = options.throws
|
|
}
|
|
|
|
fs.readFile(file, options, function (err, data) {
|
|
if (err) return callback(err)
|
|
|
|
data = stripBom(data)
|
|
|
|
var obj
|
|
try {
|
|
obj = JSON.parse(data, options ? options.reviver : null)
|
|
} catch (err2) {
|
|
if (shouldThrow) {
|
|
err2.message = file + ': ' + err2.message
|
|
return callback(err2)
|
|
} else {
|
|
return callback(null, null)
|
|
}
|
|
}
|
|
|
|
callback(null, obj)
|
|
})
|
|
}
|
|
|
|
function readFileSync (file, options) {
|
|
options = options || {}
|
|
if (typeof options === 'string') {
|
|
options = {encoding: options}
|
|
}
|
|
|
|
var fs = options.fs || _fs
|
|
|
|
var shouldThrow = true
|
|
if ('throws' in options) {
|
|
shouldThrow = options.throws
|
|
}
|
|
|
|
try {
|
|
var content = fs.readFileSync(file, options)
|
|
content = stripBom(content)
|
|
return JSON.parse(content, options.reviver)
|
|
} catch (err) {
|
|
if (shouldThrow) {
|
|
err.message = file + ': ' + err.message
|
|
throw err
|
|
} else {
|
|
return null
|
|
}
|
|
}
|
|
}
|
|
|
|
function stringify (obj, options) {
|
|
var spaces
|
|
var EOL = '\n'
|
|
if (typeof options === 'object' && options !== null) {
|
|
if (options.spaces) {
|
|
spaces = options.spaces
|
|
}
|
|
if (options.EOL) {
|
|
EOL = options.EOL
|
|
}
|
|
}
|
|
|
|
var str = JSON.stringify(obj, options ? options.replacer : null, spaces)
|
|
|
|
return str.replace(/\n/g, EOL) + EOL
|
|
}
|
|
|
|
function writeFile (file, obj, options, callback) {
|
|
if (callback == null) {
|
|
callback = options
|
|
options = {}
|
|
}
|
|
options = options || {}
|
|
var fs = options.fs || _fs
|
|
|
|
var str = ''
|
|
try {
|
|
str = stringify(obj, options)
|
|
} catch (err) {
|
|
// Need to return whether a callback was passed or not
|
|
if (callback) callback(err, null)
|
|
return
|
|
}
|
|
|
|
fs.writeFile(file, str, options, callback)
|
|
}
|
|
|
|
function writeFileSync (file, obj, options) {
|
|
options = options || {}
|
|
var fs = options.fs || _fs
|
|
|
|
var str = stringify(obj, options)
|
|
// not sure if fs.writeFileSync returns anything, but just in case
|
|
return fs.writeFileSync(file, str, options)
|
|
}
|
|
|
|
function stripBom (content) {
|
|
// we do this because JSON.parse would convert it to a utf8 string if encoding wasn't specified
|
|
if (Buffer.isBuffer(content)) content = content.toString('utf8')
|
|
content = content.replace(/^\uFEFF/, '')
|
|
return content
|
|
}
|
|
|
|
var jsonfile = {
|
|
readFile: readFile,
|
|
readFileSync: readFileSync,
|
|
writeFile: writeFile,
|
|
writeFileSync: writeFileSync
|
|
}
|
|
|
|
module.exports = jsonfile
|
|
|
|
|
|
/***/ }),
|
|
/* 126 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var fs = __webpack_require__(55)
|
|
var polyfills = __webpack_require__(127)
|
|
var legacy = __webpack_require__(128)
|
|
var clone = __webpack_require__(129)
|
|
|
|
var queue = []
|
|
|
|
var util = __webpack_require__(40)
|
|
|
|
function noop () {}
|
|
|
|
var debug = noop
|
|
if (util.debuglog)
|
|
debug = util.debuglog('gfs4')
|
|
else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || ''))
|
|
debug = function() {
|
|
var m = util.format.apply(util, arguments)
|
|
m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ')
|
|
console.error(m)
|
|
}
|
|
|
|
if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) {
|
|
process.on('exit', function() {
|
|
debug(queue)
|
|
__webpack_require__(101).equal(queue.length, 0)
|
|
})
|
|
}
|
|
|
|
module.exports = patch(clone(fs))
|
|
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) {
|
|
module.exports = patch(fs)
|
|
fs.__patched = true;
|
|
}
|
|
|
|
// Always patch fs.close/closeSync, because we want to
|
|
// retry() whenever a close happens *anywhere* in the program.
|
|
// This is essential when multiple graceful-fs instances are
|
|
// in play at the same time.
|
|
module.exports.close = (function (fs$close) { return function (fd, cb) {
|
|
return fs$close.call(fs, fd, function (err) {
|
|
if (!err)
|
|
retry()
|
|
|
|
if (typeof cb === 'function')
|
|
cb.apply(this, arguments)
|
|
})
|
|
}})(fs.close)
|
|
|
|
module.exports.closeSync = (function (fs$closeSync) { return function (fd) {
|
|
// Note that graceful-fs also retries when fs.closeSync() fails.
|
|
// Looks like a bug to me, although it's probably a harmless one.
|
|
var rval = fs$closeSync.apply(fs, arguments)
|
|
retry()
|
|
return rval
|
|
}})(fs.closeSync)
|
|
|
|
// Only patch fs once, otherwise we'll run into a memory leak if
|
|
// graceful-fs is loaded multiple times, such as in test environments that
|
|
// reset the loaded modules between tests.
|
|
// We look for the string `graceful-fs` from the comment above. This
|
|
// way we are not adding any extra properties and it will detect if older
|
|
// versions of graceful-fs are installed.
|
|
if (!/\bgraceful-fs\b/.test(fs.closeSync.toString())) {
|
|
fs.closeSync = module.exports.closeSync;
|
|
fs.close = module.exports.close;
|
|
}
|
|
|
|
function patch (fs) {
|
|
// Everything that references the open() function needs to be in here
|
|
polyfills(fs)
|
|
fs.gracefulify = patch
|
|
fs.FileReadStream = ReadStream; // Legacy name.
|
|
fs.FileWriteStream = WriteStream; // Legacy name.
|
|
fs.createReadStream = createReadStream
|
|
fs.createWriteStream = createWriteStream
|
|
var fs$readFile = fs.readFile
|
|
fs.readFile = readFile
|
|
function readFile (path, options, cb) {
|
|
if (typeof options === 'function')
|
|
cb = options, options = null
|
|
|
|
return go$readFile(path, options, cb)
|
|
|
|
function go$readFile (path, options, cb) {
|
|
return fs$readFile(path, options, function (err) {
|
|
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
|
enqueue([go$readFile, [path, options, cb]])
|
|
else {
|
|
if (typeof cb === 'function')
|
|
cb.apply(this, arguments)
|
|
retry()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
var fs$writeFile = fs.writeFile
|
|
fs.writeFile = writeFile
|
|
function writeFile (path, data, options, cb) {
|
|
if (typeof options === 'function')
|
|
cb = options, options = null
|
|
|
|
return go$writeFile(path, data, options, cb)
|
|
|
|
function go$writeFile (path, data, options, cb) {
|
|
return fs$writeFile(path, data, options, function (err) {
|
|
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
|
enqueue([go$writeFile, [path, data, options, cb]])
|
|
else {
|
|
if (typeof cb === 'function')
|
|
cb.apply(this, arguments)
|
|
retry()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
var fs$appendFile = fs.appendFile
|
|
if (fs$appendFile)
|
|
fs.appendFile = appendFile
|
|
function appendFile (path, data, options, cb) {
|
|
if (typeof options === 'function')
|
|
cb = options, options = null
|
|
|
|
return go$appendFile(path, data, options, cb)
|
|
|
|
function go$appendFile (path, data, options, cb) {
|
|
return fs$appendFile(path, data, options, function (err) {
|
|
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
|
enqueue([go$appendFile, [path, data, options, cb]])
|
|
else {
|
|
if (typeof cb === 'function')
|
|
cb.apply(this, arguments)
|
|
retry()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
var fs$readdir = fs.readdir
|
|
fs.readdir = readdir
|
|
function readdir (path, options, cb) {
|
|
var args = [path]
|
|
if (typeof options !== 'function') {
|
|
args.push(options)
|
|
} else {
|
|
cb = options
|
|
}
|
|
args.push(go$readdir$cb)
|
|
|
|
return go$readdir(args)
|
|
|
|
function go$readdir$cb (err, files) {
|
|
if (files && files.sort)
|
|
files.sort()
|
|
|
|
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
|
enqueue([go$readdir, [args]])
|
|
|
|
else {
|
|
if (typeof cb === 'function')
|
|
cb.apply(this, arguments)
|
|
retry()
|
|
}
|
|
}
|
|
}
|
|
|
|
function go$readdir (args) {
|
|
return fs$readdir.apply(fs, args)
|
|
}
|
|
|
|
if (process.version.substr(0, 4) === 'v0.8') {
|
|
var legStreams = legacy(fs)
|
|
ReadStream = legStreams.ReadStream
|
|
WriteStream = legStreams.WriteStream
|
|
}
|
|
|
|
var fs$ReadStream = fs.ReadStream
|
|
if (fs$ReadStream) {
|
|
ReadStream.prototype = Object.create(fs$ReadStream.prototype)
|
|
ReadStream.prototype.open = ReadStream$open
|
|
}
|
|
|
|
var fs$WriteStream = fs.WriteStream
|
|
if (fs$WriteStream) {
|
|
WriteStream.prototype = Object.create(fs$WriteStream.prototype)
|
|
WriteStream.prototype.open = WriteStream$open
|
|
}
|
|
|
|
fs.ReadStream = ReadStream
|
|
fs.WriteStream = WriteStream
|
|
|
|
function ReadStream (path, options) {
|
|
if (this instanceof ReadStream)
|
|
return fs$ReadStream.apply(this, arguments), this
|
|
else
|
|
return ReadStream.apply(Object.create(ReadStream.prototype), arguments)
|
|
}
|
|
|
|
function ReadStream$open () {
|
|
var that = this
|
|
open(that.path, that.flags, that.mode, function (err, fd) {
|
|
if (err) {
|
|
if (that.autoClose)
|
|
that.destroy()
|
|
|
|
that.emit('error', err)
|
|
} else {
|
|
that.fd = fd
|
|
that.emit('open', fd)
|
|
that.read()
|
|
}
|
|
})
|
|
}
|
|
|
|
function WriteStream (path, options) {
|
|
if (this instanceof WriteStream)
|
|
return fs$WriteStream.apply(this, arguments), this
|
|
else
|
|
return WriteStream.apply(Object.create(WriteStream.prototype), arguments)
|
|
}
|
|
|
|
function WriteStream$open () {
|
|
var that = this
|
|
open(that.path, that.flags, that.mode, function (err, fd) {
|
|
if (err) {
|
|
that.destroy()
|
|
that.emit('error', err)
|
|
} else {
|
|
that.fd = fd
|
|
that.emit('open', fd)
|
|
}
|
|
})
|
|
}
|
|
|
|
function createReadStream (path, options) {
|
|
return new ReadStream(path, options)
|
|
}
|
|
|
|
function createWriteStream (path, options) {
|
|
return new WriteStream(path, options)
|
|
}
|
|
|
|
var fs$open = fs.open
|
|
fs.open = open
|
|
function open (path, flags, mode, cb) {
|
|
if (typeof mode === 'function')
|
|
cb = mode, mode = null
|
|
|
|
return go$open(path, flags, mode, cb)
|
|
|
|
function go$open (path, flags, mode, cb) {
|
|
return fs$open(path, flags, mode, function (err, fd) {
|
|
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
|
enqueue([go$open, [path, flags, mode, cb]])
|
|
else {
|
|
if (typeof cb === 'function')
|
|
cb.apply(this, arguments)
|
|
retry()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
return fs
|
|
}
|
|
|
|
function enqueue (elem) {
|
|
debug('ENQUEUE', elem[0].name, elem[1])
|
|
queue.push(elem)
|
|
}
|
|
|
|
function retry () {
|
|
var elem = queue.shift()
|
|
if (elem) {
|
|
debug('RETRY', elem[0].name, elem[1])
|
|
elem[0].apply(null, elem[1])
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 127 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var constants = __webpack_require__(98)
|
|
|
|
var origCwd = process.cwd
|
|
var cwd = null
|
|
|
|
var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform
|
|
|
|
process.cwd = function() {
|
|
if (!cwd)
|
|
cwd = origCwd.call(process)
|
|
return cwd
|
|
}
|
|
try {
|
|
process.cwd()
|
|
} catch (er) {}
|
|
|
|
var chdir = process.chdir
|
|
process.chdir = function(d) {
|
|
cwd = null
|
|
chdir.call(process, d)
|
|
}
|
|
|
|
module.exports = patch
|
|
|
|
function patch (fs) {
|
|
// (re-)implement some things that are known busted or missing.
|
|
|
|
// lchmod, broken prior to 0.6.2
|
|
// back-port the fix here.
|
|
if (constants.hasOwnProperty('O_SYMLINK') &&
|
|
process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
|
|
patchLchmod(fs)
|
|
}
|
|
|
|
// lutimes implementation, or no-op
|
|
if (!fs.lutimes) {
|
|
patchLutimes(fs)
|
|
}
|
|
|
|
// https://github.com/isaacs/node-graceful-fs/issues/4
|
|
// Chown should not fail on einval or eperm if non-root.
|
|
// It should not fail on enosys ever, as this just indicates
|
|
// that a fs doesn't support the intended operation.
|
|
|
|
fs.chown = chownFix(fs.chown)
|
|
fs.fchown = chownFix(fs.fchown)
|
|
fs.lchown = chownFix(fs.lchown)
|
|
|
|
fs.chmod = chmodFix(fs.chmod)
|
|
fs.fchmod = chmodFix(fs.fchmod)
|
|
fs.lchmod = chmodFix(fs.lchmod)
|
|
|
|
fs.chownSync = chownFixSync(fs.chownSync)
|
|
fs.fchownSync = chownFixSync(fs.fchownSync)
|
|
fs.lchownSync = chownFixSync(fs.lchownSync)
|
|
|
|
fs.chmodSync = chmodFixSync(fs.chmodSync)
|
|
fs.fchmodSync = chmodFixSync(fs.fchmodSync)
|
|
fs.lchmodSync = chmodFixSync(fs.lchmodSync)
|
|
|
|
fs.stat = statFix(fs.stat)
|
|
fs.fstat = statFix(fs.fstat)
|
|
fs.lstat = statFix(fs.lstat)
|
|
|
|
fs.statSync = statFixSync(fs.statSync)
|
|
fs.fstatSync = statFixSync(fs.fstatSync)
|
|
fs.lstatSync = statFixSync(fs.lstatSync)
|
|
|
|
// if lchmod/lchown do not exist, then make them no-ops
|
|
if (!fs.lchmod) {
|
|
fs.lchmod = function (path, mode, cb) {
|
|
if (cb) process.nextTick(cb)
|
|
}
|
|
fs.lchmodSync = function () {}
|
|
}
|
|
if (!fs.lchown) {
|
|
fs.lchown = function (path, uid, gid, cb) {
|
|
if (cb) process.nextTick(cb)
|
|
}
|
|
fs.lchownSync = function () {}
|
|
}
|
|
|
|
// on Windows, A/V software can lock the directory, causing this
|
|
// to fail with an EACCES or EPERM if the directory contains newly
|
|
// created files. Try again on failure, for up to 60 seconds.
|
|
|
|
// Set the timeout this long because some Windows Anti-Virus, such as Parity
|
|
// bit9, may lock files for up to a minute, causing npm package install
|
|
// failures. Also, take care to yield the scheduler. Windows scheduling gives
|
|
// CPU to a busy looping process, which can cause the program causing the lock
|
|
// contention to be starved of CPU by node, so the contention doesn't resolve.
|
|
if (platform === "win32") {
|
|
fs.rename = (function (fs$rename) { return function (from, to, cb) {
|
|
var start = Date.now()
|
|
var backoff = 0;
|
|
fs$rename(from, to, function CB (er) {
|
|
if (er
|
|
&& (er.code === "EACCES" || er.code === "EPERM")
|
|
&& Date.now() - start < 60000) {
|
|
setTimeout(function() {
|
|
fs.stat(to, function (stater, st) {
|
|
if (stater && stater.code === "ENOENT")
|
|
fs$rename(from, to, CB);
|
|
else
|
|
cb(er)
|
|
})
|
|
}, backoff)
|
|
if (backoff < 100)
|
|
backoff += 10;
|
|
return;
|
|
}
|
|
if (cb) cb(er)
|
|
})
|
|
}})(fs.rename)
|
|
}
|
|
|
|
// if read() returns EAGAIN, then just try it again.
|
|
fs.read = (function (fs$read) { return function (fd, buffer, offset, length, position, callback_) {
|
|
var callback
|
|
if (callback_ && typeof callback_ === 'function') {
|
|
var eagCounter = 0
|
|
callback = function (er, _, __) {
|
|
if (er && er.code === 'EAGAIN' && eagCounter < 10) {
|
|
eagCounter ++
|
|
return fs$read.call(fs, fd, buffer, offset, length, position, callback)
|
|
}
|
|
callback_.apply(this, arguments)
|
|
}
|
|
}
|
|
return fs$read.call(fs, fd, buffer, offset, length, position, callback)
|
|
}})(fs.read)
|
|
|
|
fs.readSync = (function (fs$readSync) { return function (fd, buffer, offset, length, position) {
|
|
var eagCounter = 0
|
|
while (true) {
|
|
try {
|
|
return fs$readSync.call(fs, fd, buffer, offset, length, position)
|
|
} catch (er) {
|
|
if (er.code === 'EAGAIN' && eagCounter < 10) {
|
|
eagCounter ++
|
|
continue
|
|
}
|
|
throw er
|
|
}
|
|
}
|
|
}})(fs.readSync)
|
|
|
|
function patchLchmod (fs) {
|
|
fs.lchmod = function (path, mode, callback) {
|
|
fs.open( path
|
|
, constants.O_WRONLY | constants.O_SYMLINK
|
|
, mode
|
|
, function (err, fd) {
|
|
if (err) {
|
|
if (callback) callback(err)
|
|
return
|
|
}
|
|
// prefer to return the chmod error, if one occurs,
|
|
// but still try to close, and report closing errors if they occur.
|
|
fs.fchmod(fd, mode, function (err) {
|
|
fs.close(fd, function(err2) {
|
|
if (callback) callback(err || err2)
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
fs.lchmodSync = function (path, mode) {
|
|
var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode)
|
|
|
|
// prefer to return the chmod error, if one occurs,
|
|
// but still try to close, and report closing errors if they occur.
|
|
var threw = true
|
|
var ret
|
|
try {
|
|
ret = fs.fchmodSync(fd, mode)
|
|
threw = false
|
|
} finally {
|
|
if (threw) {
|
|
try {
|
|
fs.closeSync(fd)
|
|
} catch (er) {}
|
|
} else {
|
|
fs.closeSync(fd)
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
}
|
|
|
|
function patchLutimes (fs) {
|
|
if (constants.hasOwnProperty("O_SYMLINK")) {
|
|
fs.lutimes = function (path, at, mt, cb) {
|
|
fs.open(path, constants.O_SYMLINK, function (er, fd) {
|
|
if (er) {
|
|
if (cb) cb(er)
|
|
return
|
|
}
|
|
fs.futimes(fd, at, mt, function (er) {
|
|
fs.close(fd, function (er2) {
|
|
if (cb) cb(er || er2)
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
fs.lutimesSync = function (path, at, mt) {
|
|
var fd = fs.openSync(path, constants.O_SYMLINK)
|
|
var ret
|
|
var threw = true
|
|
try {
|
|
ret = fs.futimesSync(fd, at, mt)
|
|
threw = false
|
|
} finally {
|
|
if (threw) {
|
|
try {
|
|
fs.closeSync(fd)
|
|
} catch (er) {}
|
|
} else {
|
|
fs.closeSync(fd)
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
} else {
|
|
fs.lutimes = function (_a, _b, _c, cb) { if (cb) process.nextTick(cb) }
|
|
fs.lutimesSync = function () {}
|
|
}
|
|
}
|
|
|
|
function chmodFix (orig) {
|
|
if (!orig) return orig
|
|
return function (target, mode, cb) {
|
|
return orig.call(fs, target, mode, function (er) {
|
|
if (chownErOk(er)) er = null
|
|
if (cb) cb.apply(this, arguments)
|
|
})
|
|
}
|
|
}
|
|
|
|
function chmodFixSync (orig) {
|
|
if (!orig) return orig
|
|
return function (target, mode) {
|
|
try {
|
|
return orig.call(fs, target, mode)
|
|
} catch (er) {
|
|
if (!chownErOk(er)) throw er
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function chownFix (orig) {
|
|
if (!orig) return orig
|
|
return function (target, uid, gid, cb) {
|
|
return orig.call(fs, target, uid, gid, function (er) {
|
|
if (chownErOk(er)) er = null
|
|
if (cb) cb.apply(this, arguments)
|
|
})
|
|
}
|
|
}
|
|
|
|
function chownFixSync (orig) {
|
|
if (!orig) return orig
|
|
return function (target, uid, gid) {
|
|
try {
|
|
return orig.call(fs, target, uid, gid)
|
|
} catch (er) {
|
|
if (!chownErOk(er)) throw er
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function statFix (orig) {
|
|
if (!orig) return orig
|
|
// Older versions of Node erroneously returned signed integers for
|
|
// uid + gid.
|
|
return function (target, cb) {
|
|
return orig.call(fs, target, function (er, stats) {
|
|
if (!stats) return cb.apply(this, arguments)
|
|
if (stats.uid < 0) stats.uid += 0x100000000
|
|
if (stats.gid < 0) stats.gid += 0x100000000
|
|
if (cb) cb.apply(this, arguments)
|
|
})
|
|
}
|
|
}
|
|
|
|
function statFixSync (orig) {
|
|
if (!orig) return orig
|
|
// Older versions of Node erroneously returned signed integers for
|
|
// uid + gid.
|
|
return function (target) {
|
|
var stats = orig.call(fs, target)
|
|
if (stats.uid < 0) stats.uid += 0x100000000
|
|
if (stats.gid < 0) stats.gid += 0x100000000
|
|
return stats;
|
|
}
|
|
}
|
|
|
|
// ENOSYS means that the fs doesn't support the op. Just ignore
|
|
// that, because it doesn't matter.
|
|
//
|
|
// if there's no getuid, or if getuid() is something other
|
|
// than 0, and the error is EINVAL or EPERM, then just ignore
|
|
// it.
|
|
//
|
|
// This specific case is a silent failure in cp, install, tar,
|
|
// and most other unix tools that manage permissions.
|
|
//
|
|
// When running as root, or if other types of errors are
|
|
// encountered, then it's strict.
|
|
function chownErOk (er) {
|
|
if (!er)
|
|
return true
|
|
|
|
if (er.code === "ENOSYS")
|
|
return true
|
|
|
|
var nonroot = !process.getuid || process.getuid() !== 0
|
|
if (nonroot) {
|
|
if (er.code === "EINVAL" || er.code === "EPERM")
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 128 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var Stream = __webpack_require__(41).Stream
|
|
|
|
module.exports = legacy
|
|
|
|
function legacy (fs) {
|
|
return {
|
|
ReadStream: ReadStream,
|
|
WriteStream: WriteStream
|
|
}
|
|
|
|
function ReadStream (path, options) {
|
|
if (!(this instanceof ReadStream)) return new ReadStream(path, options);
|
|
|
|
Stream.call(this);
|
|
|
|
var self = this;
|
|
|
|
this.path = path;
|
|
this.fd = null;
|
|
this.readable = true;
|
|
this.paused = false;
|
|
|
|
this.flags = 'r';
|
|
this.mode = 438; /*=0666*/
|
|
this.bufferSize = 64 * 1024;
|
|
|
|
options = options || {};
|
|
|
|
// Mixin options into this
|
|
var keys = Object.keys(options);
|
|
for (var index = 0, length = keys.length; index < length; index++) {
|
|
var key = keys[index];
|
|
this[key] = options[key];
|
|
}
|
|
|
|
if (this.encoding) this.setEncoding(this.encoding);
|
|
|
|
if (this.start !== undefined) {
|
|
if ('number' !== typeof this.start) {
|
|
throw TypeError('start must be a Number');
|
|
}
|
|
if (this.end === undefined) {
|
|
this.end = Infinity;
|
|
} else if ('number' !== typeof this.end) {
|
|
throw TypeError('end must be a Number');
|
|
}
|
|
|
|
if (this.start > this.end) {
|
|
throw new Error('start must be <= end');
|
|
}
|
|
|
|
this.pos = this.start;
|
|
}
|
|
|
|
if (this.fd !== null) {
|
|
process.nextTick(function() {
|
|
self._read();
|
|
});
|
|
return;
|
|
}
|
|
|
|
fs.open(this.path, this.flags, this.mode, function (err, fd) {
|
|
if (err) {
|
|
self.emit('error', err);
|
|
self.readable = false;
|
|
return;
|
|
}
|
|
|
|
self.fd = fd;
|
|
self.emit('open', fd);
|
|
self._read();
|
|
})
|
|
}
|
|
|
|
function WriteStream (path, options) {
|
|
if (!(this instanceof WriteStream)) return new WriteStream(path, options);
|
|
|
|
Stream.call(this);
|
|
|
|
this.path = path;
|
|
this.fd = null;
|
|
this.writable = true;
|
|
|
|
this.flags = 'w';
|
|
this.encoding = 'binary';
|
|
this.mode = 438; /*=0666*/
|
|
this.bytesWritten = 0;
|
|
|
|
options = options || {};
|
|
|
|
// Mixin options into this
|
|
var keys = Object.keys(options);
|
|
for (var index = 0, length = keys.length; index < length; index++) {
|
|
var key = keys[index];
|
|
this[key] = options[key];
|
|
}
|
|
|
|
if (this.start !== undefined) {
|
|
if ('number' !== typeof this.start) {
|
|
throw TypeError('start must be a Number');
|
|
}
|
|
if (this.start < 0) {
|
|
throw new Error('start must be >= zero');
|
|
}
|
|
|
|
this.pos = this.start;
|
|
}
|
|
|
|
this.busy = false;
|
|
this._queue = [];
|
|
|
|
if (this.fd === null) {
|
|
this._open = fs.open;
|
|
this._queue.push([this._open, this.path, this.flags, this.mode, undefined]);
|
|
this.flush();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 129 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = clone
|
|
|
|
function clone (obj) {
|
|
if (obj === null || typeof obj !== 'object')
|
|
return obj
|
|
|
|
if (obj instanceof Object)
|
|
var copy = { __proto__: obj.__proto__ }
|
|
else
|
|
var copy = Object.create(null)
|
|
|
|
Object.getOwnPropertyNames(obj).forEach(function (key) {
|
|
Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key))
|
|
})
|
|
|
|
return copy
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 130 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const path = __webpack_require__(57)
|
|
const mkdir = __webpack_require__(104)
|
|
const pathExists = __webpack_require__(113).pathExists
|
|
const jsonFile = __webpack_require__(124)
|
|
|
|
function outputJson (file, data, options, callback) {
|
|
if (typeof options === 'function') {
|
|
callback = options
|
|
options = {}
|
|
}
|
|
|
|
const dir = path.dirname(file)
|
|
|
|
pathExists(dir, (err, itDoes) => {
|
|
if (err) return callback(err)
|
|
if (itDoes) return jsonFile.writeJson(file, data, options, callback)
|
|
|
|
mkdir.mkdirs(dir, err => {
|
|
if (err) return callback(err)
|
|
jsonFile.writeJson(file, data, options, callback)
|
|
})
|
|
})
|
|
}
|
|
|
|
module.exports = outputJson
|
|
|
|
|
|
/***/ }),
|
|
/* 131 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const fs = __webpack_require__(96)
|
|
const path = __webpack_require__(57)
|
|
const mkdir = __webpack_require__(104)
|
|
const jsonFile = __webpack_require__(124)
|
|
|
|
function outputJsonSync (file, data, options) {
|
|
const dir = path.dirname(file)
|
|
|
|
if (!fs.existsSync(dir)) {
|
|
mkdir.mkdirsSync(dir)
|
|
}
|
|
|
|
jsonFile.writeJsonSync(file, data, options)
|
|
}
|
|
|
|
module.exports = outputJsonSync
|
|
|
|
|
|
/***/ }),
|
|
/* 132 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = {
|
|
moveSync: __webpack_require__(133)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 133 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const fs = __webpack_require__(96)
|
|
const path = __webpack_require__(57)
|
|
const copySync = __webpack_require__(102).copySync
|
|
const removeSync = __webpack_require__(115).removeSync
|
|
const mkdirpSync = __webpack_require__(104).mkdirpSync
|
|
const stat = __webpack_require__(109)
|
|
|
|
function moveSync (src, dest, opts) {
|
|
opts = opts || {}
|
|
const overwrite = opts.overwrite || opts.clobber || false
|
|
|
|
const { srcStat } = stat.checkPathsSync(src, dest, 'move')
|
|
stat.checkParentPathsSync(src, srcStat, dest, 'move')
|
|
mkdirpSync(path.dirname(dest))
|
|
return doRename(src, dest, overwrite)
|
|
}
|
|
|
|
function doRename (src, dest, overwrite) {
|
|
if (overwrite) {
|
|
removeSync(dest)
|
|
return rename(src, dest, overwrite)
|
|
}
|
|
if (fs.existsSync(dest)) throw new Error('dest already exists.')
|
|
return rename(src, dest, overwrite)
|
|
}
|
|
|
|
function rename (src, dest, overwrite) {
|
|
try {
|
|
fs.renameSync(src, dest)
|
|
} catch (err) {
|
|
if (err.code !== 'EXDEV') throw err
|
|
return moveAcrossDevice(src, dest, overwrite)
|
|
}
|
|
}
|
|
|
|
function moveAcrossDevice (src, dest, overwrite) {
|
|
const opts = {
|
|
overwrite,
|
|
errorOnExist: true
|
|
}
|
|
copySync(src, dest, opts)
|
|
return removeSync(src)
|
|
}
|
|
|
|
module.exports = moveSync
|
|
|
|
|
|
/***/ }),
|
|
/* 134 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const u = __webpack_require__(95).fromCallback
|
|
module.exports = {
|
|
move: u(__webpack_require__(135))
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 135 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const fs = __webpack_require__(96)
|
|
const path = __webpack_require__(57)
|
|
const copy = __webpack_require__(111).copy
|
|
const remove = __webpack_require__(115).remove
|
|
const mkdirp = __webpack_require__(104).mkdirp
|
|
const pathExists = __webpack_require__(113).pathExists
|
|
const stat = __webpack_require__(109)
|
|
|
|
function move (src, dest, opts, cb) {
|
|
if (typeof opts === 'function') {
|
|
cb = opts
|
|
opts = {}
|
|
}
|
|
|
|
const overwrite = opts.overwrite || opts.clobber || false
|
|
|
|
stat.checkPaths(src, dest, 'move', (err, stats) => {
|
|
if (err) return cb(err)
|
|
const { srcStat } = stats
|
|
stat.checkParentPaths(src, srcStat, dest, 'move', err => {
|
|
if (err) return cb(err)
|
|
mkdirp(path.dirname(dest), err => {
|
|
if (err) return cb(err)
|
|
return doRename(src, dest, overwrite, cb)
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
function doRename (src, dest, overwrite, cb) {
|
|
if (overwrite) {
|
|
return remove(dest, err => {
|
|
if (err) return cb(err)
|
|
return rename(src, dest, overwrite, cb)
|
|
})
|
|
}
|
|
pathExists(dest, (err, destExists) => {
|
|
if (err) return cb(err)
|
|
if (destExists) return cb(new Error('dest already exists.'))
|
|
return rename(src, dest, overwrite, cb)
|
|
})
|
|
}
|
|
|
|
function rename (src, dest, overwrite, cb) {
|
|
fs.rename(src, dest, err => {
|
|
if (!err) return cb()
|
|
if (err.code !== 'EXDEV') return cb(err)
|
|
return moveAcrossDevice(src, dest, overwrite, cb)
|
|
})
|
|
}
|
|
|
|
function moveAcrossDevice (src, dest, overwrite, cb) {
|
|
const opts = {
|
|
overwrite,
|
|
errorOnExist: true
|
|
}
|
|
copy(src, dest, opts, err => {
|
|
if (err) return cb(err)
|
|
return remove(src, cb)
|
|
})
|
|
}
|
|
|
|
module.exports = move
|
|
|
|
|
|
/***/ }),
|
|
/* 136 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const u = __webpack_require__(95).fromCallback
|
|
const fs = __webpack_require__(96)
|
|
const path = __webpack_require__(57)
|
|
const mkdir = __webpack_require__(104)
|
|
const pathExists = __webpack_require__(113).pathExists
|
|
|
|
function outputFile (file, data, encoding, callback) {
|
|
if (typeof encoding === 'function') {
|
|
callback = encoding
|
|
encoding = 'utf8'
|
|
}
|
|
|
|
const dir = path.dirname(file)
|
|
pathExists(dir, (err, itDoes) => {
|
|
if (err) return callback(err)
|
|
if (itDoes) return fs.writeFile(file, data, encoding, callback)
|
|
|
|
mkdir.mkdirs(dir, err => {
|
|
if (err) return callback(err)
|
|
|
|
fs.writeFile(file, data, encoding, callback)
|
|
})
|
|
})
|
|
}
|
|
|
|
function outputFileSync (file, ...args) {
|
|
const dir = path.dirname(file)
|
|
if (fs.existsSync(dir)) {
|
|
return fs.writeFileSync(file, ...args)
|
|
}
|
|
mkdir.mkdirsSync(dir)
|
|
fs.writeFileSync(file, ...args)
|
|
}
|
|
|
|
module.exports = {
|
|
outputFile: u(outputFile),
|
|
outputFileSync
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 137 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("zlib");
|
|
|
|
/***/ }),
|
|
/* 138 */
|
|
/***/ (function(module, exports) {
|
|
|
|
// allows us to inject a mock date in tests
|
|
module.exports = () => new Date();
|
|
|
|
|
|
/***/ }),
|
|
/* 139 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const debug = __webpack_require__(65)("streamroller:fileNameFormatter");
|
|
const path = __webpack_require__(57);
|
|
const FILENAME_SEP = ".";
|
|
const ZIP_EXT = ".gz";
|
|
|
|
module.exports = ({
|
|
file,
|
|
keepFileExt,
|
|
needsIndex,
|
|
alwaysIncludeDate,
|
|
compress
|
|
}) => {
|
|
const dirAndName = path.join(file.dir, file.name);
|
|
|
|
const ext = f => f + file.ext;
|
|
|
|
const index = (f, i, d) =>
|
|
(needsIndex || !d) && i ? f + FILENAME_SEP + i : f;
|
|
|
|
const date = (f, i, d) => {
|
|
return (i > 0 || alwaysIncludeDate) && d ? f + FILENAME_SEP + d : f;
|
|
};
|
|
|
|
const gzip = (f, i) => (i && compress ? f + ZIP_EXT : f);
|
|
|
|
const parts = keepFileExt
|
|
? [date, index, ext, gzip]
|
|
: [ext, date, index, gzip];
|
|
|
|
return ({ date, index }) => {
|
|
debug(`_formatFileName: date=${date}, index=${index}`);
|
|
return parts.reduce(
|
|
(filename, part) => part(filename, index, date),
|
|
dirAndName
|
|
);
|
|
};
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 140 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const debug = __webpack_require__(65)("streamroller:fileNameParser");
|
|
const FILENAME_SEP = ".";
|
|
const ZIP_EXT = ".gz";
|
|
const format = __webpack_require__(76);
|
|
|
|
module.exports = ({ file, keepFileExt, pattern }) => {
|
|
// All these functions take two arguments: f, the filename, and p, the result placeholder
|
|
// They return the filename with any matching parts removed.
|
|
// The "zip" function, for instance, removes the ".gz" part of the filename (if present)
|
|
const zip = (f, p) => {
|
|
if (f.endsWith(ZIP_EXT)) {
|
|
debug("it is gzipped");
|
|
p.isCompressed = true;
|
|
return f.slice(0, -1 * ZIP_EXT.length);
|
|
}
|
|
return f;
|
|
};
|
|
|
|
const extAtEnd = f => {
|
|
if (f.startsWith(file.name) && f.endsWith(file.ext)) {
|
|
debug("it starts and ends with the right things");
|
|
return f.slice(file.name.length + 1, -1 * file.ext.length);
|
|
}
|
|
return f;
|
|
};
|
|
|
|
const extInMiddle = f => {
|
|
if (f.startsWith(file.base)) {
|
|
debug("it starts with the right things");
|
|
return f.slice(file.base.length + 1);
|
|
}
|
|
return f;
|
|
};
|
|
|
|
const dateAndIndex = (f, p) => {
|
|
const items = f.split(FILENAME_SEP);
|
|
let indexStr = items[items.length - 1];
|
|
debug("items: ", items, ", indexStr: ", indexStr);
|
|
let dateStr = f;
|
|
if (indexStr !== undefined && indexStr.match(/^\d+$/)) {
|
|
dateStr = f.slice(0, -1 * (indexStr.length + 1));
|
|
debug(`dateStr is ${dateStr}`);
|
|
} else {
|
|
indexStr = "0";
|
|
}
|
|
|
|
try {
|
|
// Two arguments for new Date() are intentional. This will set other date
|
|
// components to minimal values in the current timezone instead of UTC,
|
|
// as new Date(0) will do.
|
|
const date = format.parse(pattern, dateStr, new Date(0, 0));
|
|
p.index = parseInt(indexStr, 10);
|
|
p.date = dateStr;
|
|
p.timestamp = date.getTime();
|
|
return "";
|
|
} catch (e) {
|
|
//not a valid date, don't panic.
|
|
debug(`Problem parsing ${dateStr} as ${pattern}, error was: `, e);
|
|
return f;
|
|
}
|
|
};
|
|
|
|
const index = (f, p) => {
|
|
if (f.match(/^\d+$/)) {
|
|
debug("it has an index");
|
|
p.index = parseInt(f, 10);
|
|
return "";
|
|
}
|
|
return f;
|
|
};
|
|
|
|
let parts = [
|
|
zip,
|
|
keepFileExt ? extAtEnd : extInMiddle,
|
|
pattern ? dateAndIndex : index
|
|
];
|
|
|
|
return filename => {
|
|
let result = { filename, index: 0, isCompressed: false };
|
|
// pass the filename through each of the file part parsers
|
|
let whatsLeftOver = parts.reduce(
|
|
(remains, part) => part(remains, result),
|
|
filename
|
|
);
|
|
// if there's anything left after parsing, then it wasn't a valid filename
|
|
return whatsLeftOver ? null : result;
|
|
};
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 141 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const RollingFileWriteStream = __webpack_require__(92);
|
|
|
|
// just to adapt the previous version
|
|
class RollingFileStream extends RollingFileWriteStream {
|
|
constructor(filename, size, backups, options) {
|
|
if (!options) {
|
|
options = {};
|
|
}
|
|
if (size) {
|
|
options.maxSize = size;
|
|
}
|
|
if (!backups) {
|
|
backups = 1;
|
|
}
|
|
options.numToKeep = backups;
|
|
super(filename, options);
|
|
this.backups = this.options.numToKeep;
|
|
this.size = this.options.maxSize;
|
|
}
|
|
|
|
get theStream() {
|
|
return this.currentFileStream;
|
|
}
|
|
|
|
}
|
|
|
|
module.exports = RollingFileStream;
|
|
|
|
|
|
/***/ }),
|
|
/* 142 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const RollingFileWriteStream = __webpack_require__(92);
|
|
|
|
// just to adapt the previous version
|
|
class DateRollingFileStream extends RollingFileWriteStream {
|
|
constructor(filename, pattern, options) {
|
|
if (pattern && typeof(pattern) === 'object') {
|
|
options = pattern;
|
|
pattern = null;
|
|
}
|
|
if (!options) {
|
|
options = {};
|
|
}
|
|
if (!pattern) {
|
|
pattern = 'yyyy-MM-dd';
|
|
}
|
|
if (options.daysToKeep) {
|
|
options.numToKeep = options.daysToKeep;
|
|
}
|
|
if (pattern.startsWith('.')) {
|
|
pattern = pattern.substring(1);
|
|
}
|
|
options.pattern = pattern;
|
|
super(filename, options);
|
|
this.mode = this.options.mode;
|
|
}
|
|
|
|
get theStream() {
|
|
return this.currentFileStream;
|
|
}
|
|
|
|
}
|
|
|
|
module.exports = DateRollingFileStream;
|
|
|
|
|
|
/***/ }),
|
|
/* 143 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const streams = __webpack_require__(91);
|
|
const os = __webpack_require__(56);
|
|
|
|
const eol = os.EOL || '\n';
|
|
|
|
/**
|
|
* File appender that rolls files according to a date pattern.
|
|
* @filename base filename.
|
|
* @pattern the format that will be added to the end of filename when rolling,
|
|
* also used to check when to roll files - defaults to '.yyyy-MM-dd'
|
|
* @layout layout function for log messages - defaults to basicLayout
|
|
* @timezoneOffset optional timezone offset in minutes - defaults to system local
|
|
*/
|
|
function appender(
|
|
filename,
|
|
pattern,
|
|
layout,
|
|
options,
|
|
timezoneOffset
|
|
) {
|
|
// the options for file appender use maxLogSize, but the docs say any file appender
|
|
// options should work for dateFile as well.
|
|
options.maxSize = options.maxLogSize;
|
|
|
|
const logFile = new streams.DateRollingFileStream(
|
|
filename,
|
|
pattern,
|
|
options
|
|
);
|
|
|
|
const app = function (logEvent) {
|
|
logFile.write(layout(logEvent, timezoneOffset) + eol, 'utf8');
|
|
};
|
|
|
|
app.shutdown = function (complete) {
|
|
logFile.write('', 'utf-8', () => {
|
|
logFile.end(complete);
|
|
});
|
|
};
|
|
|
|
return app;
|
|
}
|
|
|
|
function configure(config, layouts) {
|
|
let layout = layouts.basicLayout;
|
|
|
|
if (config.layout) {
|
|
layout = layouts.layout(config.layout.type, config.layout);
|
|
}
|
|
|
|
if (!config.alwaysIncludePattern) {
|
|
config.alwaysIncludePattern = false;
|
|
}
|
|
|
|
return appender(
|
|
config.filename,
|
|
config.pattern,
|
|
layout,
|
|
config,
|
|
config.timezoneOffset
|
|
);
|
|
}
|
|
|
|
module.exports.configure = configure;
|
|
|
|
|
|
/***/ }),
|
|
/* 144 */
|
|
/***/ (function(module, exports) {
|
|
|
|
function webpackEmptyContext(req) {
|
|
var e = new Error("Cannot find module '" + req + "'");
|
|
e.code = 'MODULE_NOT_FOUND';
|
|
throw e;
|
|
}
|
|
webpackEmptyContext.keys = function() { return []; };
|
|
webpackEmptyContext.resolve = webpackEmptyContext;
|
|
module.exports = webpackEmptyContext;
|
|
webpackEmptyContext.id = 144;
|
|
|
|
/***/ }),
|
|
/* 145 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const debug = __webpack_require__(65)('log4js:categories');
|
|
const configuration = __webpack_require__(74);
|
|
const levels = __webpack_require__(77);
|
|
const appenders = __webpack_require__(78);
|
|
|
|
const categories = new Map();
|
|
|
|
/**
|
|
* Add inherited config to this category. That includes extra appenders from parent,
|
|
* and level, if none is set on this category.
|
|
* This is recursive, so each parent also gets loaded with inherited appenders.
|
|
* Inheritance is blocked if a category has inherit=false
|
|
* @param {any} config
|
|
* @param {any} category the child category
|
|
* @param {string} categoryName dotted path to category
|
|
* @return {void}
|
|
*/
|
|
function inheritFromParent(config, category, categoryName) {
|
|
if (category.inherit === false) return;
|
|
const lastDotIndex = categoryName.lastIndexOf('.');
|
|
if (lastDotIndex < 0) return; // category is not a child
|
|
const parentCategoryName = categoryName.substring(0, lastDotIndex);
|
|
let parentCategory = config.categories[parentCategoryName];
|
|
|
|
|
|
if (!parentCategory) {
|
|
// parent is missing, so implicitly create it, so that it can inherit from its parents
|
|
parentCategory = { inherit: true, appenders: [] };
|
|
}
|
|
|
|
// make sure parent has had its inheritance taken care of before pulling its properties to this child
|
|
inheritFromParent(config, parentCategory, parentCategoryName);
|
|
|
|
// if the parent is not in the config (because we just created it above),
|
|
// and it inherited a valid configuration, add it to config.categories
|
|
if (!config.categories[parentCategoryName]
|
|
&& parentCategory.appenders
|
|
&& parentCategory.appenders.length
|
|
&& parentCategory.level) {
|
|
config.categories[parentCategoryName] = parentCategory;
|
|
}
|
|
|
|
category.appenders = category.appenders || [];
|
|
category.level = category.level || parentCategory.level;
|
|
|
|
// merge in appenders from parent (parent is already holding its inherited appenders)
|
|
parentCategory.appenders.forEach((ap) => {
|
|
if (!category.appenders.includes(ap)) {
|
|
category.appenders.push(ap);
|
|
}
|
|
});
|
|
category.parent = parentCategory;
|
|
}
|
|
|
|
|
|
/**
|
|
* Walk all categories in the config, and pull down any configuration from parent to child.
|
|
* This includes inherited appenders, and level, where level is not set.
|
|
* Inheritance is skipped where a category has inherit=false.
|
|
* @param {any} config
|
|
*/
|
|
function addCategoryInheritance(config) {
|
|
if (!config.categories) return;
|
|
const categoryNames = Object.keys(config.categories);
|
|
categoryNames.forEach((name) => {
|
|
const category = config.categories[name];
|
|
// add inherited appenders and level to this category
|
|
inheritFromParent(config, category, name);
|
|
});
|
|
}
|
|
|
|
configuration.addPreProcessingListener(config => addCategoryInheritance(config));
|
|
|
|
configuration.addListener((config) => {
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(configuration.anObject(config.categories)),
|
|
'must have a property "categories" of type object.'
|
|
);
|
|
|
|
const categoryNames = Object.keys(config.categories);
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(categoryNames.length),
|
|
'must define at least one category.'
|
|
);
|
|
|
|
categoryNames.forEach((name) => {
|
|
const category = config.categories[name];
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
[
|
|
configuration.not(category.appenders),
|
|
configuration.not(category.level)
|
|
],
|
|
`category "${name}" is not valid (must be an object with properties "appenders" and "level")`
|
|
);
|
|
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(Array.isArray(category.appenders)),
|
|
`category "${name}" is not valid (appenders must be an array of appender names)`
|
|
);
|
|
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(category.appenders.length),
|
|
`category "${name}" is not valid (appenders must contain at least one appender name)`
|
|
);
|
|
|
|
if (Object.prototype.hasOwnProperty.call(category, 'enableCallStack')) {
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
typeof category.enableCallStack !== 'boolean',
|
|
`category "${name}" is not valid (enableCallStack must be boolean type)`
|
|
);
|
|
}
|
|
|
|
category.appenders.forEach((appender) => {
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(appenders.get(appender)),
|
|
`category "${name}" is not valid (appender "${appender}" is not defined)`
|
|
);
|
|
});
|
|
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(levels.getLevel(category.level)),
|
|
`category "${name}" is not valid (level "${category.level}" not recognised;`
|
|
+ ` valid levels are ${levels.levels.join(', ')})`
|
|
);
|
|
});
|
|
|
|
configuration.throwExceptionIf(
|
|
config,
|
|
configuration.not(config.categories.default),
|
|
'must define a "default" category.'
|
|
);
|
|
});
|
|
|
|
const setup = (config) => {
|
|
categories.clear();
|
|
|
|
const categoryNames = Object.keys(config.categories);
|
|
categoryNames.forEach((name) => {
|
|
const category = config.categories[name];
|
|
const categoryAppenders = [];
|
|
category.appenders.forEach((appender) => {
|
|
categoryAppenders.push(appenders.get(appender));
|
|
debug(`Creating category ${name}`);
|
|
categories.set(
|
|
name,
|
|
{
|
|
appenders: categoryAppenders,
|
|
level: levels.getLevel(category.level),
|
|
enableCallStack: category.enableCallStack || false
|
|
}
|
|
);
|
|
});
|
|
});
|
|
};
|
|
|
|
setup({ categories: { default: { appenders: ['out'], level: 'OFF' } } });
|
|
configuration.addListener(setup);
|
|
|
|
const configForCategory = (category) => {
|
|
debug(`configForCategory: searching for config for ${category}`);
|
|
if (categories.has(category)) {
|
|
debug(`configForCategory: ${category} exists in config, returning it`);
|
|
return categories.get(category);
|
|
}
|
|
if (category.indexOf('.') > 0) {
|
|
debug(`configForCategory: ${category} has hierarchy, searching for parents`);
|
|
return configForCategory(category.substring(0, category.lastIndexOf('.')));
|
|
}
|
|
debug('configForCategory: returning config for default category');
|
|
return configForCategory('default');
|
|
};
|
|
|
|
const appendersForCategory = category => configForCategory(category).appenders;
|
|
const getLevelForCategory = category => configForCategory(category).level;
|
|
|
|
const setLevelForCategory = (category, level) => {
|
|
let categoryConfig = categories.get(category);
|
|
debug(`setLevelForCategory: found ${categoryConfig} for ${category}`);
|
|
if (!categoryConfig) {
|
|
const sourceCategoryConfig = configForCategory(category);
|
|
debug('setLevelForCategory: no config found for category, '
|
|
+ `found ${sourceCategoryConfig} for parents of ${category}`);
|
|
categoryConfig = { appenders: sourceCategoryConfig.appenders };
|
|
}
|
|
categoryConfig.level = level;
|
|
categories.set(category, categoryConfig);
|
|
};
|
|
|
|
const getEnableCallStackForCategory = category => configForCategory(category).enableCallStack === true;
|
|
const setEnableCallStackForCategory = (category, useCallStack) => {
|
|
configForCategory(category).enableCallStack = useCallStack;
|
|
};
|
|
|
|
module.exports = {
|
|
appendersForCategory,
|
|
getLevelForCategory,
|
|
setLevelForCategory,
|
|
getEnableCallStackForCategory,
|
|
setEnableCallStackForCategory,
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 146 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* eslint no-underscore-dangle:0 */
|
|
const debug = __webpack_require__(65)("log4js:logger");
|
|
const LoggingEvent = __webpack_require__(80);
|
|
const levels = __webpack_require__(77);
|
|
const clustering = __webpack_require__(79);
|
|
const categories = __webpack_require__(145);
|
|
const configuration = __webpack_require__(74);
|
|
|
|
const stackReg = /at (?:(.+)\s+\()?(?:(.+?):(\d+)(?::(\d+))?|([^)]+))\)?/;
|
|
function defaultParseCallStack(data, skipIdx = 4) {
|
|
const stacklines = data.stack.split("\n").slice(skipIdx);
|
|
const lineMatch = stackReg.exec(stacklines[0]);
|
|
if (lineMatch && lineMatch.length === 6) {
|
|
return {
|
|
functionName: lineMatch[1],
|
|
fileName: lineMatch[2],
|
|
lineNumber: parseInt(lineMatch[3], 10),
|
|
columnNumber: parseInt(lineMatch[4], 10),
|
|
callStack: stacklines.join("\n")
|
|
};
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Logger to log messages.
|
|
* use {@see log4js#getLogger(String)} to get an instance.
|
|
*
|
|
* @name Logger
|
|
* @namespace Log4js
|
|
* @param name name of category to log to
|
|
* @param level - the loglevel for the category
|
|
* @param dispatch - the function which will receive the logevents
|
|
*
|
|
* @author Stephan Strittmatter
|
|
*/
|
|
class Logger {
|
|
constructor(name) {
|
|
if (!name) {
|
|
throw new Error("No category provided.");
|
|
}
|
|
this.category = name;
|
|
this.context = {};
|
|
this.parseCallStack = defaultParseCallStack;
|
|
debug(`Logger created (${this.category}, ${this.level})`);
|
|
}
|
|
|
|
get level() {
|
|
return levels.getLevel(
|
|
categories.getLevelForCategory(this.category),
|
|
levels.TRACE
|
|
);
|
|
}
|
|
|
|
set level(level) {
|
|
categories.setLevelForCategory(
|
|
this.category,
|
|
levels.getLevel(level, this.level)
|
|
);
|
|
}
|
|
|
|
get useCallStack() {
|
|
return categories.getEnableCallStackForCategory(this.category);
|
|
}
|
|
|
|
set useCallStack(bool) {
|
|
categories.setEnableCallStackForCategory(this.category, bool === true);
|
|
}
|
|
|
|
log(level, ...args) {
|
|
const logLevel = levels.getLevel(level, levels.INFO);
|
|
if (this.isLevelEnabled(logLevel)) {
|
|
this._log(logLevel, args);
|
|
}
|
|
}
|
|
|
|
isLevelEnabled(otherLevel) {
|
|
return this.level.isLessThanOrEqualTo(otherLevel);
|
|
}
|
|
|
|
_log(level, data) {
|
|
debug(`sending log data (${level}) to appenders`);
|
|
const loggingEvent = new LoggingEvent(
|
|
this.category,
|
|
level,
|
|
data,
|
|
this.context,
|
|
this.useCallStack && this.parseCallStack(new Error())
|
|
);
|
|
clustering.send(loggingEvent);
|
|
}
|
|
|
|
addContext(key, value) {
|
|
this.context[key] = value;
|
|
}
|
|
|
|
removeContext(key) {
|
|
delete this.context[key];
|
|
}
|
|
|
|
clearContext() {
|
|
this.context = {};
|
|
}
|
|
|
|
setParseCallStackFunction(parseFunction) {
|
|
this.parseCallStack = parseFunction;
|
|
}
|
|
}
|
|
|
|
function addLevelMethods(target) {
|
|
const level = levels.getLevel(target);
|
|
|
|
const levelStrLower = level.toString().toLowerCase();
|
|
const levelMethod = levelStrLower.replace(/_([a-z])/g, g =>
|
|
g[1].toUpperCase()
|
|
);
|
|
const isLevelMethod = levelMethod[0].toUpperCase() + levelMethod.slice(1);
|
|
|
|
Logger.prototype[`is${isLevelMethod}Enabled`] = function() {
|
|
return this.isLevelEnabled(level);
|
|
};
|
|
|
|
Logger.prototype[levelMethod] = function(...args) {
|
|
this.log(level, ...args);
|
|
};
|
|
}
|
|
|
|
levels.levels.forEach(addLevelMethods);
|
|
|
|
configuration.addListener(() => {
|
|
levels.levels.forEach(addLevelMethods);
|
|
});
|
|
|
|
module.exports = Logger;
|
|
|
|
|
|
/***/ }),
|
|
/* 147 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* eslint-disable no-plusplus */
|
|
|
|
const levels = __webpack_require__(77);
|
|
|
|
const DEFAULT_FORMAT =
|
|
":remote-addr - -" +
|
|
' ":method :url HTTP/:http-version"' +
|
|
' :status :content-length ":referrer"' +
|
|
' ":user-agent"';
|
|
|
|
/**
|
|
* Return request url path,
|
|
* adding this function prevents the Cyclomatic Complexity,
|
|
* for the assemble_tokens function at low, to pass the tests.
|
|
*
|
|
* @param {IncomingMessage} req
|
|
* @return {String}
|
|
* @api private
|
|
*/
|
|
function getUrl(req) {
|
|
return req.originalUrl || req.url;
|
|
}
|
|
|
|
/**
|
|
* Adds custom {token, replacement} objects to defaults,
|
|
* overwriting the defaults if any tokens clash
|
|
*
|
|
* @param {IncomingMessage} req
|
|
* @param {ServerResponse} res
|
|
* @param {Array} customTokens
|
|
* [{ token: string-or-regexp, replacement: string-or-replace-function }]
|
|
* @return {Array}
|
|
*/
|
|
function assembleTokens(req, res, customTokens) {
|
|
const arrayUniqueTokens = array => {
|
|
const a = array.concat();
|
|
for (let i = 0; i < a.length; ++i) {
|
|
for (let j = i + 1; j < a.length; ++j) {
|
|
// not === because token can be regexp object
|
|
/* eslint eqeqeq:0 */
|
|
if (a[i].token == a[j].token) {
|
|
a.splice(j--, 1);
|
|
}
|
|
}
|
|
}
|
|
return a;
|
|
};
|
|
|
|
const defaultTokens = [];
|
|
defaultTokens.push({ token: ":url", replacement: getUrl(req) });
|
|
defaultTokens.push({ token: ":protocol", replacement: req.protocol });
|
|
defaultTokens.push({ token: ":hostname", replacement: req.hostname });
|
|
defaultTokens.push({ token: ":method", replacement: req.method });
|
|
defaultTokens.push({
|
|
token: ":status",
|
|
replacement: res.__statusCode || res.statusCode
|
|
});
|
|
defaultTokens.push({
|
|
token: ":response-time",
|
|
replacement: res.responseTime
|
|
});
|
|
defaultTokens.push({ token: ":date", replacement: new Date().toUTCString() });
|
|
defaultTokens.push({
|
|
token: ":referrer",
|
|
replacement: req.headers.referer || req.headers.referrer || ""
|
|
});
|
|
defaultTokens.push({
|
|
token: ":http-version",
|
|
replacement: `${req.httpVersionMajor}.${req.httpVersionMinor}`
|
|
});
|
|
defaultTokens.push({
|
|
token: ":remote-addr",
|
|
replacement:
|
|
req.headers["x-forwarded-for"] ||
|
|
req.ip ||
|
|
req._remoteAddress ||
|
|
(req.socket &&
|
|
(req.socket.remoteAddress ||
|
|
(req.socket.socket && req.socket.socket.remoteAddress)))
|
|
});
|
|
defaultTokens.push({
|
|
token: ":user-agent",
|
|
replacement: req.headers["user-agent"]
|
|
});
|
|
defaultTokens.push({
|
|
token: ":content-length",
|
|
replacement:
|
|
res.getHeader("content-length") ||
|
|
(res.__headers && res.__headers["Content-Length"]) ||
|
|
"-"
|
|
});
|
|
defaultTokens.push({
|
|
token: /:req\[([^\]]+)]/g,
|
|
replacement(_, field) {
|
|
return req.headers[field.toLowerCase()];
|
|
}
|
|
});
|
|
defaultTokens.push({
|
|
token: /:res\[([^\]]+)]/g,
|
|
replacement(_, field) {
|
|
return (
|
|
res.getHeader(field.toLowerCase()) ||
|
|
(res.__headers && res.__headers[field])
|
|
);
|
|
}
|
|
});
|
|
|
|
return arrayUniqueTokens(customTokens.concat(defaultTokens));
|
|
}
|
|
|
|
/**
|
|
* Return formatted log line.
|
|
*
|
|
* @param {String} str
|
|
* @param {Array} tokens
|
|
* @return {String}
|
|
* @api private
|
|
*/
|
|
function format(str, tokens) {
|
|
for (let i = 0; i < tokens.length; i++) {
|
|
str = str.replace(tokens[i].token, tokens[i].replacement);
|
|
}
|
|
return str;
|
|
}
|
|
|
|
/**
|
|
* Return RegExp Object about nolog
|
|
*
|
|
* @param {String|Array} nolog
|
|
* @return {RegExp}
|
|
* @api private
|
|
*
|
|
* syntax
|
|
* 1. String
|
|
* 1.1 "\\.gif"
|
|
* NOT LOGGING http://example.com/hoge.gif and http://example.com/hoge.gif?fuga
|
|
* LOGGING http://example.com/hoge.agif
|
|
* 1.2 in "\\.gif|\\.jpg$"
|
|
* NOT LOGGING http://example.com/hoge.gif and
|
|
* http://example.com/hoge.gif?fuga and http://example.com/hoge.jpg?fuga
|
|
* LOGGING http://example.com/hoge.agif,
|
|
* http://example.com/hoge.ajpg and http://example.com/hoge.jpg?hoge
|
|
* 1.3 in "\\.(gif|jpe?g|png)$"
|
|
* NOT LOGGING http://example.com/hoge.gif and http://example.com/hoge.jpeg
|
|
* LOGGING http://example.com/hoge.gif?uid=2 and http://example.com/hoge.jpg?pid=3
|
|
* 2. RegExp
|
|
* 2.1 in /\.(gif|jpe?g|png)$/
|
|
* SAME AS 1.3
|
|
* 3. Array
|
|
* 3.1 ["\\.jpg$", "\\.png", "\\.gif"]
|
|
* SAME AS "\\.jpg|\\.png|\\.gif"
|
|
*/
|
|
function createNoLogCondition(nolog) {
|
|
let regexp = null;
|
|
|
|
if (nolog instanceof RegExp) {
|
|
regexp = nolog;
|
|
}
|
|
|
|
if (typeof nolog === "string") {
|
|
regexp = new RegExp(nolog);
|
|
}
|
|
|
|
if (Array.isArray(nolog)) {
|
|
// convert to strings
|
|
const regexpsAsStrings = nolog.map(reg => (reg.source ? reg.source : reg));
|
|
regexp = new RegExp(regexpsAsStrings.join("|"));
|
|
}
|
|
|
|
return regexp;
|
|
}
|
|
|
|
/**
|
|
* Allows users to define rules around status codes to assign them to a specific
|
|
* logging level.
|
|
* There are two types of rules:
|
|
* - RANGE: matches a code within a certain range
|
|
* E.g. { 'from': 200, 'to': 299, 'level': 'info' }
|
|
* - CONTAINS: matches a code to a set of expected codes
|
|
* E.g. { 'codes': [200, 203], 'level': 'debug' }
|
|
* Note*: Rules are respected only in order of prescendence.
|
|
*
|
|
* @param {Number} statusCode
|
|
* @param {Level} currentLevel
|
|
* @param {Object} ruleSet
|
|
* @return {Level}
|
|
* @api private
|
|
*/
|
|
function matchRules(statusCode, currentLevel, ruleSet) {
|
|
let level = currentLevel;
|
|
|
|
if (ruleSet) {
|
|
const matchedRule = ruleSet.find(rule => {
|
|
let ruleMatched = false;
|
|
if (rule.from && rule.to) {
|
|
ruleMatched = statusCode >= rule.from && statusCode <= rule.to;
|
|
} else {
|
|
ruleMatched = rule.codes.indexOf(statusCode) !== -1;
|
|
}
|
|
return ruleMatched;
|
|
});
|
|
if (matchedRule) {
|
|
level = levels.getLevel(matchedRule.level, level);
|
|
}
|
|
}
|
|
return level;
|
|
}
|
|
|
|
/**
|
|
* Log requests with the given `options` or a `format` string.
|
|
*
|
|
* Options:
|
|
*
|
|
* - `format` Format string, see below for tokens
|
|
* - `level` A log4js levels instance. Supports also 'auto'
|
|
* - `nolog` A string or RegExp to exclude target logs
|
|
* - `statusRules` A array of rules for setting specific logging levels base on status codes
|
|
* - `context` Whether to add a response of express to the context
|
|
*
|
|
* Tokens:
|
|
*
|
|
* - `:req[header]` ex: `:req[Accept]`
|
|
* - `:res[header]` ex: `:res[Content-Length]`
|
|
* - `:http-version`
|
|
* - `:response-time`
|
|
* - `:remote-addr`
|
|
* - `:date`
|
|
* - `:method`
|
|
* - `:url`
|
|
* - `:referrer`
|
|
* - `:user-agent`
|
|
* - `:status`
|
|
*
|
|
* @return {Function}
|
|
* @param logger4js
|
|
* @param options
|
|
* @api public
|
|
*/
|
|
module.exports = function getLogger(logger4js, options) {
|
|
/* eslint no-underscore-dangle:0 */
|
|
if (typeof options === "string" || typeof options === "function") {
|
|
options = { format: options };
|
|
} else {
|
|
options = options || {};
|
|
}
|
|
|
|
const thisLogger = logger4js;
|
|
let level = levels.getLevel(options.level, levels.INFO);
|
|
const fmt = options.format || DEFAULT_FORMAT;
|
|
const nolog = createNoLogCondition(options.nolog);
|
|
|
|
return (req, res, next) => {
|
|
// mount safety
|
|
if (req._logging) return next();
|
|
|
|
// nologs
|
|
if (nolog && nolog.test(req.originalUrl)) return next();
|
|
|
|
if (thisLogger.isLevelEnabled(level) || options.level === "auto") {
|
|
const start = new Date();
|
|
const { writeHead } = res;
|
|
|
|
// flag as logging
|
|
req._logging = true;
|
|
|
|
// proxy for statusCode.
|
|
res.writeHead = (code, headers) => {
|
|
res.writeHead = writeHead;
|
|
res.writeHead(code, headers);
|
|
|
|
res.__statusCode = code;
|
|
res.__headers = headers || {};
|
|
};
|
|
|
|
// hook on end request to emit the log entry of the HTTP request.
|
|
res.on("finish", () => {
|
|
res.responseTime = new Date() - start;
|
|
// status code response level handling
|
|
if (res.statusCode && options.level === "auto") {
|
|
level = levels.INFO;
|
|
if (res.statusCode >= 300) level = levels.WARN;
|
|
if (res.statusCode >= 400) level = levels.ERROR;
|
|
}
|
|
level = matchRules(res.statusCode, level, options.statusRules);
|
|
|
|
const combinedTokens = assembleTokens(req, res, options.tokens || []);
|
|
|
|
if (options.context) thisLogger.addContext("res", res);
|
|
if (typeof fmt === "function") {
|
|
const line = fmt(req, res, str => format(str, combinedTokens));
|
|
if (line) thisLogger.log(level, line);
|
|
} else {
|
|
thisLogger.log(level, format(fmt, combinedTokens));
|
|
}
|
|
if (options.context) thisLogger.removeContext("res");
|
|
});
|
|
}
|
|
|
|
// ensure next gets always called
|
|
return next();
|
|
};
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 148 */
|
|
/***/ (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__(149);
|
|
const util_1 = __webpack_require__(174);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('events');
|
|
class Events {
|
|
constructor() {
|
|
this.handlers = new Map();
|
|
this.insertMode = false;
|
|
}
|
|
get cursor() {
|
|
return this._cursor;
|
|
}
|
|
async fire(event, args) {
|
|
logger.debug('Event:', event, args);
|
|
let handlers = this.handlers.get(event);
|
|
if (event == 'InsertEnter') {
|
|
this.insertMode = true;
|
|
}
|
|
else if (event == 'InsertLeave') {
|
|
this.insertMode = false;
|
|
}
|
|
else if (!this.insertMode && (event == 'CursorHoldI' || event == 'CursorMovedI')) {
|
|
this.insertMode = true;
|
|
await this.fire('InsertEnter', [args[0]]);
|
|
}
|
|
else if (this.insertMode && (event == 'CursorHold' || event == 'CursorMoved')) {
|
|
this.insertMode = false;
|
|
await this.fire('InsertLeave', [args[0]]);
|
|
}
|
|
if (event == 'CursorMoved' || event == 'CursorMovedI') {
|
|
this._cursor = {
|
|
bufnr: args[0],
|
|
lnum: args[1][0],
|
|
col: args[1][1],
|
|
insert: event == 'CursorMovedI'
|
|
};
|
|
}
|
|
if (handlers) {
|
|
try {
|
|
await Promise.all(handlers.map(fn => {
|
|
return Promise.resolve(fn.apply(null, args));
|
|
}));
|
|
}
|
|
catch (e) {
|
|
logger.error(`Error on ${event}: `, e.stack);
|
|
workspace_1.default.showMessage(`Error on ${event}: ${e.message} `, 'error');
|
|
}
|
|
}
|
|
}
|
|
on(event, handler, thisArg, disposables) {
|
|
if (Array.isArray(event)) {
|
|
let disposables = [];
|
|
for (let ev of event) {
|
|
disposables.push(this.on(ev, handler, thisArg, disposables));
|
|
}
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
util_1.disposeAll(disposables);
|
|
});
|
|
}
|
|
else {
|
|
let arr = this.handlers.get(event) || [];
|
|
arr.push(handler.bind(thisArg || null));
|
|
this.handlers.set(event, arr);
|
|
let disposable = vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
let idx = arr.indexOf(handler);
|
|
if (idx !== -1) {
|
|
arr.splice(idx, 1);
|
|
}
|
|
});
|
|
if (disposables) {
|
|
disposables.push(disposable);
|
|
}
|
|
return disposable;
|
|
}
|
|
}
|
|
}
|
|
exports.default = new Events();
|
|
//# sourceMappingURL=events.js.map
|
|
|
|
/***/ }),
|
|
/* 149 */
|
|
/***/ (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.
|
|
* ------------------------------------------------------------------------------------------ */
|
|
|
|
function __export(m) {
|
|
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|
}
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const vscode_jsonrpc_1 = __webpack_require__(150);
|
|
exports.ErrorCodes = vscode_jsonrpc_1.ErrorCodes;
|
|
exports.ResponseError = vscode_jsonrpc_1.ResponseError;
|
|
exports.CancellationToken = vscode_jsonrpc_1.CancellationToken;
|
|
exports.CancellationTokenSource = vscode_jsonrpc_1.CancellationTokenSource;
|
|
exports.Disposable = vscode_jsonrpc_1.Disposable;
|
|
exports.Event = vscode_jsonrpc_1.Event;
|
|
exports.Emitter = vscode_jsonrpc_1.Emitter;
|
|
exports.Trace = vscode_jsonrpc_1.Trace;
|
|
exports.TraceFormat = vscode_jsonrpc_1.TraceFormat;
|
|
exports.SetTraceNotification = vscode_jsonrpc_1.SetTraceNotification;
|
|
exports.LogTraceNotification = vscode_jsonrpc_1.LogTraceNotification;
|
|
exports.RequestType = vscode_jsonrpc_1.RequestType;
|
|
exports.RequestType0 = vscode_jsonrpc_1.RequestType0;
|
|
exports.NotificationType = vscode_jsonrpc_1.NotificationType;
|
|
exports.NotificationType0 = vscode_jsonrpc_1.NotificationType0;
|
|
exports.MessageReader = vscode_jsonrpc_1.MessageReader;
|
|
exports.MessageWriter = vscode_jsonrpc_1.MessageWriter;
|
|
exports.ConnectionStrategy = vscode_jsonrpc_1.ConnectionStrategy;
|
|
exports.StreamMessageReader = vscode_jsonrpc_1.StreamMessageReader;
|
|
exports.StreamMessageWriter = vscode_jsonrpc_1.StreamMessageWriter;
|
|
exports.IPCMessageReader = vscode_jsonrpc_1.IPCMessageReader;
|
|
exports.IPCMessageWriter = vscode_jsonrpc_1.IPCMessageWriter;
|
|
exports.createClientPipeTransport = vscode_jsonrpc_1.createClientPipeTransport;
|
|
exports.createServerPipeTransport = vscode_jsonrpc_1.createServerPipeTransport;
|
|
exports.generateRandomPipeName = vscode_jsonrpc_1.generateRandomPipeName;
|
|
exports.createClientSocketTransport = vscode_jsonrpc_1.createClientSocketTransport;
|
|
exports.createServerSocketTransport = vscode_jsonrpc_1.createServerSocketTransport;
|
|
__export(__webpack_require__(161));
|
|
__export(__webpack_require__(162));
|
|
const callHierarchy = __webpack_require__(172);
|
|
const progress = __webpack_require__(173);
|
|
var Proposed;
|
|
(function (Proposed) {
|
|
let CallHierarchyRequest;
|
|
(function (CallHierarchyRequest) {
|
|
CallHierarchyRequest.type = callHierarchy.CallHierarchyRequest.type;
|
|
})(CallHierarchyRequest = Proposed.CallHierarchyRequest || (Proposed.CallHierarchyRequest = {}));
|
|
let CallHierarchyDirection;
|
|
(function (CallHierarchyDirection) {
|
|
CallHierarchyDirection.CallsFrom = callHierarchy.CallHierarchyDirection.CallsFrom;
|
|
CallHierarchyDirection.CallsTo = callHierarchy.CallHierarchyDirection.CallsTo;
|
|
})(CallHierarchyDirection = Proposed.CallHierarchyDirection || (Proposed.CallHierarchyDirection = {}));
|
|
let ProgressStartNotification;
|
|
(function (ProgressStartNotification) {
|
|
ProgressStartNotification.type = progress.ProgressStartNotification.type;
|
|
})(ProgressStartNotification = Proposed.ProgressStartNotification || (Proposed.ProgressStartNotification = {}));
|
|
let ProgressReportNotification;
|
|
(function (ProgressReportNotification) {
|
|
ProgressReportNotification.type = progress.ProgressReportNotification.type;
|
|
})(ProgressReportNotification = Proposed.ProgressReportNotification || (Proposed.ProgressReportNotification = {}));
|
|
let ProgressDoneNotification;
|
|
(function (ProgressDoneNotification) {
|
|
ProgressDoneNotification.type = progress.ProgressDoneNotification.type;
|
|
})(ProgressDoneNotification = Proposed.ProgressDoneNotification || (Proposed.ProgressDoneNotification = {}));
|
|
let ProgressCancelNotification;
|
|
(function (ProgressCancelNotification) {
|
|
ProgressCancelNotification.type = progress.ProgressCancelNotification.type;
|
|
})(ProgressCancelNotification = Proposed.ProgressCancelNotification || (Proposed.ProgressCancelNotification = {}));
|
|
})(Proposed = exports.Proposed || (exports.Proposed = {}));
|
|
function createProtocolConnection(reader, writer, logger, strategy) {
|
|
return vscode_jsonrpc_1.createMessageConnection(reader, writer, logger, strategy);
|
|
}
|
|
exports.createProtocolConnection = createProtocolConnection;
|
|
|
|
|
|
/***/ }),
|
|
/* 150 */
|
|
/***/ (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.
|
|
* ------------------------------------------------------------------------------------------ */
|
|
/// <reference path="./thenable.ts" />
|
|
|
|
function __export(m) {
|
|
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|
}
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const Is = __webpack_require__(151);
|
|
const messages_1 = __webpack_require__(152);
|
|
exports.RequestType = messages_1.RequestType;
|
|
exports.RequestType0 = messages_1.RequestType0;
|
|
exports.RequestType1 = messages_1.RequestType1;
|
|
exports.RequestType2 = messages_1.RequestType2;
|
|
exports.RequestType3 = messages_1.RequestType3;
|
|
exports.RequestType4 = messages_1.RequestType4;
|
|
exports.RequestType5 = messages_1.RequestType5;
|
|
exports.RequestType6 = messages_1.RequestType6;
|
|
exports.RequestType7 = messages_1.RequestType7;
|
|
exports.RequestType8 = messages_1.RequestType8;
|
|
exports.RequestType9 = messages_1.RequestType9;
|
|
exports.ResponseError = messages_1.ResponseError;
|
|
exports.ErrorCodes = messages_1.ErrorCodes;
|
|
exports.NotificationType = messages_1.NotificationType;
|
|
exports.NotificationType0 = messages_1.NotificationType0;
|
|
exports.NotificationType1 = messages_1.NotificationType1;
|
|
exports.NotificationType2 = messages_1.NotificationType2;
|
|
exports.NotificationType3 = messages_1.NotificationType3;
|
|
exports.NotificationType4 = messages_1.NotificationType4;
|
|
exports.NotificationType5 = messages_1.NotificationType5;
|
|
exports.NotificationType6 = messages_1.NotificationType6;
|
|
exports.NotificationType7 = messages_1.NotificationType7;
|
|
exports.NotificationType8 = messages_1.NotificationType8;
|
|
exports.NotificationType9 = messages_1.NotificationType9;
|
|
const messageReader_1 = __webpack_require__(153);
|
|
exports.MessageReader = messageReader_1.MessageReader;
|
|
exports.StreamMessageReader = messageReader_1.StreamMessageReader;
|
|
exports.IPCMessageReader = messageReader_1.IPCMessageReader;
|
|
exports.SocketMessageReader = messageReader_1.SocketMessageReader;
|
|
const messageWriter_1 = __webpack_require__(155);
|
|
exports.MessageWriter = messageWriter_1.MessageWriter;
|
|
exports.StreamMessageWriter = messageWriter_1.StreamMessageWriter;
|
|
exports.IPCMessageWriter = messageWriter_1.IPCMessageWriter;
|
|
exports.SocketMessageWriter = messageWriter_1.SocketMessageWriter;
|
|
const events_1 = __webpack_require__(154);
|
|
exports.Disposable = events_1.Disposable;
|
|
exports.Event = events_1.Event;
|
|
exports.Emitter = events_1.Emitter;
|
|
const cancellation_1 = __webpack_require__(156);
|
|
exports.CancellationTokenSource = cancellation_1.CancellationTokenSource;
|
|
exports.CancellationToken = cancellation_1.CancellationToken;
|
|
const linkedMap_1 = __webpack_require__(157);
|
|
__export(__webpack_require__(158));
|
|
__export(__webpack_require__(160));
|
|
var CancelNotification;
|
|
(function (CancelNotification) {
|
|
CancelNotification.type = new messages_1.NotificationType('$/cancelRequest');
|
|
})(CancelNotification || (CancelNotification = {}));
|
|
exports.NullLogger = Object.freeze({
|
|
error: () => { },
|
|
warn: () => { },
|
|
info: () => { },
|
|
log: () => { }
|
|
});
|
|
var Trace;
|
|
(function (Trace) {
|
|
Trace[Trace["Off"] = 0] = "Off";
|
|
Trace[Trace["Messages"] = 1] = "Messages";
|
|
Trace[Trace["Verbose"] = 2] = "Verbose";
|
|
})(Trace = exports.Trace || (exports.Trace = {}));
|
|
(function (Trace) {
|
|
function fromString(value) {
|
|
value = value.toLowerCase();
|
|
switch (value) {
|
|
case 'off':
|
|
return Trace.Off;
|
|
case 'messages':
|
|
return Trace.Messages;
|
|
case 'verbose':
|
|
return Trace.Verbose;
|
|
default:
|
|
return Trace.Off;
|
|
}
|
|
}
|
|
Trace.fromString = fromString;
|
|
function toString(value) {
|
|
switch (value) {
|
|
case Trace.Off:
|
|
return 'off';
|
|
case Trace.Messages:
|
|
return 'messages';
|
|
case Trace.Verbose:
|
|
return 'verbose';
|
|
default:
|
|
return 'off';
|
|
}
|
|
}
|
|
Trace.toString = toString;
|
|
})(Trace = exports.Trace || (exports.Trace = {}));
|
|
var TraceFormat;
|
|
(function (TraceFormat) {
|
|
TraceFormat["Text"] = "text";
|
|
TraceFormat["JSON"] = "json";
|
|
})(TraceFormat = exports.TraceFormat || (exports.TraceFormat = {}));
|
|
(function (TraceFormat) {
|
|
function fromString(value) {
|
|
value = value.toLowerCase();
|
|
if (value === 'json') {
|
|
return TraceFormat.JSON;
|
|
}
|
|
else {
|
|
return TraceFormat.Text;
|
|
}
|
|
}
|
|
TraceFormat.fromString = fromString;
|
|
})(TraceFormat = exports.TraceFormat || (exports.TraceFormat = {}));
|
|
var SetTraceNotification;
|
|
(function (SetTraceNotification) {
|
|
SetTraceNotification.type = new messages_1.NotificationType('$/setTraceNotification');
|
|
})(SetTraceNotification = exports.SetTraceNotification || (exports.SetTraceNotification = {}));
|
|
var LogTraceNotification;
|
|
(function (LogTraceNotification) {
|
|
LogTraceNotification.type = new messages_1.NotificationType('$/logTraceNotification');
|
|
})(LogTraceNotification = exports.LogTraceNotification || (exports.LogTraceNotification = {}));
|
|
var ConnectionErrors;
|
|
(function (ConnectionErrors) {
|
|
/**
|
|
* The connection is closed.
|
|
*/
|
|
ConnectionErrors[ConnectionErrors["Closed"] = 1] = "Closed";
|
|
/**
|
|
* The connection got disposed.
|
|
*/
|
|
ConnectionErrors[ConnectionErrors["Disposed"] = 2] = "Disposed";
|
|
/**
|
|
* The connection is already in listening mode.
|
|
*/
|
|
ConnectionErrors[ConnectionErrors["AlreadyListening"] = 3] = "AlreadyListening";
|
|
})(ConnectionErrors = exports.ConnectionErrors || (exports.ConnectionErrors = {}));
|
|
class ConnectionError extends Error {
|
|
constructor(code, message) {
|
|
super(message);
|
|
this.code = code;
|
|
Object.setPrototypeOf(this, ConnectionError.prototype);
|
|
}
|
|
}
|
|
exports.ConnectionError = ConnectionError;
|
|
var ConnectionStrategy;
|
|
(function (ConnectionStrategy) {
|
|
function is(value) {
|
|
let candidate = value;
|
|
return candidate && Is.func(candidate.cancelUndispatched);
|
|
}
|
|
ConnectionStrategy.is = is;
|
|
})(ConnectionStrategy = exports.ConnectionStrategy || (exports.ConnectionStrategy = {}));
|
|
var ConnectionState;
|
|
(function (ConnectionState) {
|
|
ConnectionState[ConnectionState["New"] = 1] = "New";
|
|
ConnectionState[ConnectionState["Listening"] = 2] = "Listening";
|
|
ConnectionState[ConnectionState["Closed"] = 3] = "Closed";
|
|
ConnectionState[ConnectionState["Disposed"] = 4] = "Disposed";
|
|
})(ConnectionState || (ConnectionState = {}));
|
|
function _createMessageConnection(messageReader, messageWriter, logger, strategy) {
|
|
let sequenceNumber = 0;
|
|
let notificationSquenceNumber = 0;
|
|
let unknownResponseSquenceNumber = 0;
|
|
const version = '2.0';
|
|
let starRequestHandler = undefined;
|
|
let requestHandlers = Object.create(null);
|
|
let starNotificationHandler = undefined;
|
|
let notificationHandlers = Object.create(null);
|
|
let timer;
|
|
let messageQueue = new linkedMap_1.LinkedMap();
|
|
let responsePromises = Object.create(null);
|
|
let requestTokens = Object.create(null);
|
|
let trace = Trace.Off;
|
|
let traceFormat = TraceFormat.Text;
|
|
let tracer;
|
|
let state = ConnectionState.New;
|
|
let errorEmitter = new events_1.Emitter();
|
|
let closeEmitter = new events_1.Emitter();
|
|
let unhandledNotificationEmitter = new events_1.Emitter();
|
|
let disposeEmitter = new events_1.Emitter();
|
|
function createRequestQueueKey(id) {
|
|
return 'req-' + id.toString();
|
|
}
|
|
function createResponseQueueKey(id) {
|
|
if (id === null) {
|
|
return 'res-unknown-' + (++unknownResponseSquenceNumber).toString();
|
|
}
|
|
else {
|
|
return 'res-' + id.toString();
|
|
}
|
|
}
|
|
function createNotificationQueueKey() {
|
|
return 'not-' + (++notificationSquenceNumber).toString();
|
|
}
|
|
function addMessageToQueue(queue, message) {
|
|
if (messages_1.isRequestMessage(message)) {
|
|
queue.set(createRequestQueueKey(message.id), message);
|
|
}
|
|
else if (messages_1.isResponseMessage(message)) {
|
|
queue.set(createResponseQueueKey(message.id), message);
|
|
}
|
|
else {
|
|
queue.set(createNotificationQueueKey(), message);
|
|
}
|
|
}
|
|
function cancelUndispatched(_message) {
|
|
return undefined;
|
|
}
|
|
function isListening() {
|
|
return state === ConnectionState.Listening;
|
|
}
|
|
function isClosed() {
|
|
return state === ConnectionState.Closed;
|
|
}
|
|
function isDisposed() {
|
|
return state === ConnectionState.Disposed;
|
|
}
|
|
function closeHandler() {
|
|
if (state === ConnectionState.New || state === ConnectionState.Listening) {
|
|
state = ConnectionState.Closed;
|
|
closeEmitter.fire(undefined);
|
|
}
|
|
// If the connection is disposed don't sent close events.
|
|
}
|
|
;
|
|
function readErrorHandler(error) {
|
|
errorEmitter.fire([error, undefined, undefined]);
|
|
}
|
|
function writeErrorHandler(data) {
|
|
errorEmitter.fire(data);
|
|
}
|
|
messageReader.onClose(closeHandler);
|
|
messageReader.onError(readErrorHandler);
|
|
messageWriter.onClose(closeHandler);
|
|
messageWriter.onError(writeErrorHandler);
|
|
function triggerMessageQueue() {
|
|
if (timer || messageQueue.size === 0) {
|
|
return;
|
|
}
|
|
timer = setImmediate(() => {
|
|
timer = undefined;
|
|
processMessageQueue();
|
|
});
|
|
}
|
|
function processMessageQueue() {
|
|
if (messageQueue.size === 0) {
|
|
return;
|
|
}
|
|
let message = messageQueue.shift();
|
|
try {
|
|
if (messages_1.isRequestMessage(message)) {
|
|
handleRequest(message);
|
|
}
|
|
else if (messages_1.isNotificationMessage(message)) {
|
|
handleNotification(message);
|
|
}
|
|
else if (messages_1.isResponseMessage(message)) {
|
|
handleResponse(message);
|
|
}
|
|
else {
|
|
handleInvalidMessage(message);
|
|
}
|
|
}
|
|
finally {
|
|
triggerMessageQueue();
|
|
}
|
|
}
|
|
let callback = (message) => {
|
|
try {
|
|
// We have received a cancellation message. Check if the message is still in the queue
|
|
// and cancel it if allowed to do so.
|
|
if (messages_1.isNotificationMessage(message) && message.method === CancelNotification.type.method) {
|
|
let key = createRequestQueueKey(message.params.id);
|
|
let toCancel = messageQueue.get(key);
|
|
if (messages_1.isRequestMessage(toCancel)) {
|
|
let response = strategy && strategy.cancelUndispatched ? strategy.cancelUndispatched(toCancel, cancelUndispatched) : cancelUndispatched(toCancel);
|
|
if (response && (response.error !== void 0 || response.result !== void 0)) {
|
|
messageQueue.delete(key);
|
|
response.id = toCancel.id;
|
|
traceSendingResponse(response, message.method, Date.now());
|
|
messageWriter.write(response);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
addMessageToQueue(messageQueue, message);
|
|
}
|
|
finally {
|
|
triggerMessageQueue();
|
|
}
|
|
};
|
|
function handleRequest(requestMessage) {
|
|
if (isDisposed()) {
|
|
// we return here silently since we fired an event when the
|
|
// connection got disposed.
|
|
return;
|
|
}
|
|
function reply(resultOrError, method, startTime) {
|
|
let message = {
|
|
jsonrpc: version,
|
|
id: requestMessage.id
|
|
};
|
|
if (resultOrError instanceof messages_1.ResponseError) {
|
|
message.error = resultOrError.toJson();
|
|
}
|
|
else {
|
|
message.result = resultOrError === void 0 ? null : resultOrError;
|
|
}
|
|
traceSendingResponse(message, method, startTime);
|
|
messageWriter.write(message);
|
|
}
|
|
function replyError(error, method, startTime) {
|
|
let message = {
|
|
jsonrpc: version,
|
|
id: requestMessage.id,
|
|
error: error.toJson()
|
|
};
|
|
traceSendingResponse(message, method, startTime);
|
|
messageWriter.write(message);
|
|
}
|
|
function replySuccess(result, method, startTime) {
|
|
// The JSON RPC defines that a response must either have a result or an error
|
|
// So we can't treat undefined as a valid response result.
|
|
if (result === void 0) {
|
|
result = null;
|
|
}
|
|
let message = {
|
|
jsonrpc: version,
|
|
id: requestMessage.id,
|
|
result: result
|
|
};
|
|
traceSendingResponse(message, method, startTime);
|
|
messageWriter.write(message);
|
|
}
|
|
traceReceivedRequest(requestMessage);
|
|
let element = requestHandlers[requestMessage.method];
|
|
let type;
|
|
let requestHandler;
|
|
if (element) {
|
|
type = element.type;
|
|
requestHandler = element.handler;
|
|
}
|
|
let startTime = Date.now();
|
|
if (requestHandler || starRequestHandler) {
|
|
let cancellationSource = new cancellation_1.CancellationTokenSource();
|
|
let tokenKey = String(requestMessage.id);
|
|
requestTokens[tokenKey] = cancellationSource;
|
|
try {
|
|
let handlerResult;
|
|
if (requestMessage.params === void 0 || (type !== void 0 && type.numberOfParams === 0)) {
|
|
handlerResult = requestHandler
|
|
? requestHandler(cancellationSource.token)
|
|
: starRequestHandler(requestMessage.method, cancellationSource.token);
|
|
}
|
|
else if (Is.array(requestMessage.params) && (type === void 0 || type.numberOfParams > 1)) {
|
|
handlerResult = requestHandler
|
|
? requestHandler(...requestMessage.params, cancellationSource.token)
|
|
: starRequestHandler(requestMessage.method, ...requestMessage.params, cancellationSource.token);
|
|
}
|
|
else {
|
|
handlerResult = requestHandler
|
|
? requestHandler(requestMessage.params, cancellationSource.token)
|
|
: starRequestHandler(requestMessage.method, requestMessage.params, cancellationSource.token);
|
|
}
|
|
let promise = handlerResult;
|
|
if (!handlerResult) {
|
|
delete requestTokens[tokenKey];
|
|
replySuccess(handlerResult, requestMessage.method, startTime);
|
|
}
|
|
else if (promise.then) {
|
|
promise.then((resultOrError) => {
|
|
delete requestTokens[tokenKey];
|
|
reply(resultOrError, requestMessage.method, startTime);
|
|
}, error => {
|
|
delete requestTokens[tokenKey];
|
|
if (error instanceof messages_1.ResponseError) {
|
|
replyError(error, requestMessage.method, startTime);
|
|
}
|
|
else if (error && Is.string(error.message)) {
|
|
replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InternalError, `Request ${requestMessage.method} failed with message: ${error.message}`), requestMessage.method, startTime);
|
|
}
|
|
else {
|
|
replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InternalError, `Request ${requestMessage.method} failed unexpectedly without providing any details.`), requestMessage.method, startTime);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
delete requestTokens[tokenKey];
|
|
reply(handlerResult, requestMessage.method, startTime);
|
|
}
|
|
}
|
|
catch (error) {
|
|
delete requestTokens[tokenKey];
|
|
if (error instanceof messages_1.ResponseError) {
|
|
reply(error, requestMessage.method, startTime);
|
|
}
|
|
else if (error && Is.string(error.message)) {
|
|
replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InternalError, `Request ${requestMessage.method} failed with message: ${error.message}`), requestMessage.method, startTime);
|
|
}
|
|
else {
|
|
replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InternalError, `Request ${requestMessage.method} failed unexpectedly without providing any details.`), requestMessage.method, startTime);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
replyError(new messages_1.ResponseError(messages_1.ErrorCodes.MethodNotFound, `Unhandled method ${requestMessage.method}`), requestMessage.method, startTime);
|
|
}
|
|
}
|
|
function handleResponse(responseMessage) {
|
|
if (isDisposed()) {
|
|
// See handle request.
|
|
return;
|
|
}
|
|
if (responseMessage.id === null) {
|
|
if (responseMessage.error) {
|
|
logger.error(`Received response message without id: Error is: \n${JSON.stringify(responseMessage.error, undefined, 4)}`);
|
|
}
|
|
else {
|
|
logger.error(`Received response message without id. No further error information provided.`);
|
|
}
|
|
}
|
|
else {
|
|
let key = String(responseMessage.id);
|
|
let responsePromise = responsePromises[key];
|
|
traceReceivedResponse(responseMessage, responsePromise);
|
|
if (responsePromise) {
|
|
delete responsePromises[key];
|
|
try {
|
|
if (responseMessage.error) {
|
|
let error = responseMessage.error;
|
|
responsePromise.reject(new messages_1.ResponseError(error.code, error.message, error.data));
|
|
}
|
|
else if (responseMessage.result !== void 0) {
|
|
responsePromise.resolve(responseMessage.result);
|
|
}
|
|
else {
|
|
throw new Error('Should never happen.');
|
|
}
|
|
}
|
|
catch (error) {
|
|
if (error.message) {
|
|
logger.error(`Response handler '${responsePromise.method}' failed with message: ${error.message}`);
|
|
}
|
|
else {
|
|
logger.error(`Response handler '${responsePromise.method}' failed unexpectedly.`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function handleNotification(message) {
|
|
if (isDisposed()) {
|
|
// See handle request.
|
|
return;
|
|
}
|
|
let type = undefined;
|
|
let notificationHandler;
|
|
if (message.method === CancelNotification.type.method) {
|
|
notificationHandler = (params) => {
|
|
let id = params.id;
|
|
let source = requestTokens[String(id)];
|
|
if (source) {
|
|
source.cancel();
|
|
}
|
|
};
|
|
}
|
|
else {
|
|
let element = notificationHandlers[message.method];
|
|
if (element) {
|
|
notificationHandler = element.handler;
|
|
type = element.type;
|
|
}
|
|
}
|
|
if (notificationHandler || starNotificationHandler) {
|
|
try {
|
|
traceReceivedNotification(message);
|
|
if (message.params === void 0 || (type !== void 0 && type.numberOfParams === 0)) {
|
|
notificationHandler ? notificationHandler() : starNotificationHandler(message.method);
|
|
}
|
|
else if (Is.array(message.params) && (type === void 0 || type.numberOfParams > 1)) {
|
|
notificationHandler ? notificationHandler(...message.params) : starNotificationHandler(message.method, ...message.params);
|
|
}
|
|
else {
|
|
notificationHandler ? notificationHandler(message.params) : starNotificationHandler(message.method, message.params);
|
|
}
|
|
}
|
|
catch (error) {
|
|
if (error.message) {
|
|
logger.error(`Notification handler '${message.method}' failed with message: ${error.message}`);
|
|
}
|
|
else {
|
|
logger.error(`Notification handler '${message.method}' failed unexpectedly.`);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
unhandledNotificationEmitter.fire(message);
|
|
}
|
|
}
|
|
function handleInvalidMessage(message) {
|
|
if (!message) {
|
|
logger.error('Received empty message.');
|
|
return;
|
|
}
|
|
logger.error(`Received message which is neither a response nor a notification message:\n${JSON.stringify(message, null, 4)}`);
|
|
// Test whether we find an id to reject the promise
|
|
let responseMessage = message;
|
|
if (Is.string(responseMessage.id) || Is.number(responseMessage.id)) {
|
|
let key = String(responseMessage.id);
|
|
let responseHandler = responsePromises[key];
|
|
if (responseHandler) {
|
|
responseHandler.reject(new Error('The received response has neither a result nor an error property.'));
|
|
}
|
|
}
|
|
}
|
|
function traceSendingRequest(message) {
|
|
if (trace === Trace.Off || !tracer) {
|
|
return;
|
|
}
|
|
if (traceFormat === TraceFormat.Text) {
|
|
let data = undefined;
|
|
if (trace === Trace.Verbose && message.params) {
|
|
data = `Params: ${JSON.stringify(message.params, null, 4)}\n\n`;
|
|
}
|
|
tracer.log(`Sending request '${message.method} - (${message.id})'.`, data);
|
|
}
|
|
else {
|
|
logLSPMessage('send-request', message);
|
|
}
|
|
}
|
|
function traceSendingNotification(message) {
|
|
if (trace === Trace.Off || !tracer) {
|
|
return;
|
|
}
|
|
if (traceFormat === TraceFormat.Text) {
|
|
let data = undefined;
|
|
if (trace === Trace.Verbose) {
|
|
if (message.params) {
|
|
data = `Params: ${JSON.stringify(message.params, null, 4)}\n\n`;
|
|
}
|
|
else {
|
|
data = 'No parameters provided.\n\n';
|
|
}
|
|
}
|
|
tracer.log(`Sending notification '${message.method}'.`, data);
|
|
}
|
|
else {
|
|
logLSPMessage('send-notification', message);
|
|
}
|
|
}
|
|
function traceSendingResponse(message, method, startTime) {
|
|
if (trace === Trace.Off || !tracer) {
|
|
return;
|
|
}
|
|
if (traceFormat === TraceFormat.Text) {
|
|
let data = undefined;
|
|
if (trace === Trace.Verbose) {
|
|
if (message.error && message.error.data) {
|
|
data = `Error data: ${JSON.stringify(message.error.data, null, 4)}\n\n`;
|
|
}
|
|
else {
|
|
if (message.result) {
|
|
data = `Result: ${JSON.stringify(message.result, null, 4)}\n\n`;
|
|
}
|
|
else if (message.error === void 0) {
|
|
data = 'No result returned.\n\n';
|
|
}
|
|
}
|
|
}
|
|
tracer.log(`Sending response '${method} - (${message.id})'. Processing request took ${Date.now() - startTime}ms`, data);
|
|
}
|
|
else {
|
|
logLSPMessage('send-response', message);
|
|
}
|
|
}
|
|
function traceReceivedRequest(message) {
|
|
if (trace === Trace.Off || !tracer) {
|
|
return;
|
|
}
|
|
if (traceFormat === TraceFormat.Text) {
|
|
let data = undefined;
|
|
if (trace === Trace.Verbose && message.params) {
|
|
data = `Params: ${JSON.stringify(message.params, null, 4)}\n\n`;
|
|
}
|
|
tracer.log(`Received request '${message.method} - (${message.id})'.`, data);
|
|
}
|
|
else {
|
|
logLSPMessage('receive-request', message);
|
|
}
|
|
}
|
|
function traceReceivedNotification(message) {
|
|
if (trace === Trace.Off || !tracer || message.method === LogTraceNotification.type.method) {
|
|
return;
|
|
}
|
|
if (traceFormat === TraceFormat.Text) {
|
|
let data = undefined;
|
|
if (trace === Trace.Verbose) {
|
|
if (message.params) {
|
|
data = `Params: ${JSON.stringify(message.params, null, 4)}\n\n`;
|
|
}
|
|
else {
|
|
data = 'No parameters provided.\n\n';
|
|
}
|
|
}
|
|
tracer.log(`Received notification '${message.method}'.`, data);
|
|
}
|
|
else {
|
|
logLSPMessage('receive-notification', message);
|
|
}
|
|
}
|
|
function traceReceivedResponse(message, responsePromise) {
|
|
if (trace === Trace.Off || !tracer) {
|
|
return;
|
|
}
|
|
if (traceFormat === TraceFormat.Text) {
|
|
let data = undefined;
|
|
if (trace === Trace.Verbose) {
|
|
if (message.error && message.error.data) {
|
|
data = `Error data: ${JSON.stringify(message.error.data, null, 4)}\n\n`;
|
|
}
|
|
else {
|
|
if (message.result) {
|
|
data = `Result: ${JSON.stringify(message.result, null, 4)}\n\n`;
|
|
}
|
|
else if (message.error === void 0) {
|
|
data = 'No result returned.\n\n';
|
|
}
|
|
}
|
|
}
|
|
if (responsePromise) {
|
|
let error = message.error ? ` Request failed: ${message.error.message} (${message.error.code}).` : '';
|
|
tracer.log(`Received response '${responsePromise.method} - (${message.id})' in ${Date.now() - responsePromise.timerStart}ms.${error}`, data);
|
|
}
|
|
else {
|
|
tracer.log(`Received response ${message.id} without active response promise.`, data);
|
|
}
|
|
}
|
|
else {
|
|
logLSPMessage('receive-response', message);
|
|
}
|
|
}
|
|
function logLSPMessage(type, message) {
|
|
if (!tracer || trace === Trace.Off) {
|
|
return;
|
|
}
|
|
const lspMessage = {
|
|
isLSPMessage: true,
|
|
type,
|
|
message,
|
|
timestamp: Date.now()
|
|
};
|
|
tracer.log(lspMessage);
|
|
}
|
|
function throwIfClosedOrDisposed() {
|
|
if (isClosed()) {
|
|
throw new ConnectionError(ConnectionErrors.Closed, 'Connection is closed.');
|
|
}
|
|
if (isDisposed()) {
|
|
throw new ConnectionError(ConnectionErrors.Disposed, 'Connection is disposed.');
|
|
}
|
|
}
|
|
function throwIfListening() {
|
|
if (isListening()) {
|
|
throw new ConnectionError(ConnectionErrors.AlreadyListening, 'Connection is already listening');
|
|
}
|
|
}
|
|
function throwIfNotListening() {
|
|
if (!isListening()) {
|
|
throw new Error('Call listen() first.');
|
|
}
|
|
}
|
|
function undefinedToNull(param) {
|
|
if (param === void 0) {
|
|
return null;
|
|
}
|
|
else {
|
|
return param;
|
|
}
|
|
}
|
|
function computeMessageParams(type, params) {
|
|
let result;
|
|
let numberOfParams = type.numberOfParams;
|
|
switch (numberOfParams) {
|
|
case 0:
|
|
result = null;
|
|
break;
|
|
case 1:
|
|
result = undefinedToNull(params[0]);
|
|
break;
|
|
default:
|
|
result = [];
|
|
for (let i = 0; i < params.length && i < numberOfParams; i++) {
|
|
result.push(undefinedToNull(params[i]));
|
|
}
|
|
if (params.length < numberOfParams) {
|
|
for (let i = params.length; i < numberOfParams; i++) {
|
|
result.push(null);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
let connection = {
|
|
sendNotification: (type, ...params) => {
|
|
throwIfClosedOrDisposed();
|
|
let method;
|
|
let messageParams;
|
|
if (Is.string(type)) {
|
|
method = type;
|
|
switch (params.length) {
|
|
case 0:
|
|
messageParams = null;
|
|
break;
|
|
case 1:
|
|
messageParams = params[0];
|
|
break;
|
|
default:
|
|
messageParams = params;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
method = type.method;
|
|
messageParams = computeMessageParams(type, params);
|
|
}
|
|
let notificationMessage = {
|
|
jsonrpc: version,
|
|
method: method,
|
|
params: messageParams
|
|
};
|
|
traceSendingNotification(notificationMessage);
|
|
messageWriter.write(notificationMessage);
|
|
},
|
|
onNotification: (type, handler) => {
|
|
throwIfClosedOrDisposed();
|
|
if (Is.func(type)) {
|
|
starNotificationHandler = type;
|
|
}
|
|
else if (handler) {
|
|
if (Is.string(type)) {
|
|
notificationHandlers[type] = { type: undefined, handler };
|
|
}
|
|
else {
|
|
notificationHandlers[type.method] = { type, handler };
|
|
}
|
|
}
|
|
},
|
|
sendRequest: (type, ...params) => {
|
|
throwIfClosedOrDisposed();
|
|
throwIfNotListening();
|
|
let method;
|
|
let messageParams;
|
|
let token = undefined;
|
|
if (Is.string(type)) {
|
|
method = type;
|
|
switch (params.length) {
|
|
case 0:
|
|
messageParams = null;
|
|
break;
|
|
case 1:
|
|
// The cancellation token is optional so it can also be undefined.
|
|
if (cancellation_1.CancellationToken.is(params[0])) {
|
|
messageParams = null;
|
|
token = params[0];
|
|
}
|
|
else {
|
|
messageParams = undefinedToNull(params[0]);
|
|
}
|
|
break;
|
|
default:
|
|
const last = params.length - 1;
|
|
if (cancellation_1.CancellationToken.is(params[last])) {
|
|
token = params[last];
|
|
if (params.length === 2) {
|
|
messageParams = undefinedToNull(params[0]);
|
|
}
|
|
else {
|
|
messageParams = params.slice(0, last).map(value => undefinedToNull(value));
|
|
}
|
|
}
|
|
else {
|
|
messageParams = params.map(value => undefinedToNull(value));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
method = type.method;
|
|
messageParams = computeMessageParams(type, params);
|
|
let numberOfParams = type.numberOfParams;
|
|
token = cancellation_1.CancellationToken.is(params[numberOfParams]) ? params[numberOfParams] : undefined;
|
|
}
|
|
let id = sequenceNumber++;
|
|
let result = new Promise((resolve, reject) => {
|
|
let requestMessage = {
|
|
jsonrpc: version,
|
|
id: id,
|
|
method: method,
|
|
params: messageParams
|
|
};
|
|
let responsePromise = { method: method, timerStart: Date.now(), resolve, reject };
|
|
traceSendingRequest(requestMessage);
|
|
try {
|
|
messageWriter.write(requestMessage);
|
|
}
|
|
catch (e) {
|
|
// Writing the message failed. So we need to reject the promise.
|
|
responsePromise.reject(new messages_1.ResponseError(messages_1.ErrorCodes.MessageWriteError, e.message ? e.message : 'Unknown reason'));
|
|
responsePromise = null;
|
|
}
|
|
if (responsePromise) {
|
|
responsePromises[String(id)] = responsePromise;
|
|
}
|
|
});
|
|
if (token) {
|
|
token.onCancellationRequested(() => {
|
|
connection.sendNotification(CancelNotification.type, { id });
|
|
});
|
|
}
|
|
return result;
|
|
},
|
|
onRequest: (type, handler) => {
|
|
throwIfClosedOrDisposed();
|
|
if (Is.func(type)) {
|
|
starRequestHandler = type;
|
|
}
|
|
else if (handler) {
|
|
if (Is.string(type)) {
|
|
requestHandlers[type] = { type: undefined, handler };
|
|
}
|
|
else {
|
|
requestHandlers[type.method] = { type, handler };
|
|
}
|
|
}
|
|
},
|
|
trace: (_value, _tracer, sendNotificationOrTraceOptions) => {
|
|
let _sendNotification = false;
|
|
let _traceFormat = TraceFormat.Text;
|
|
if (sendNotificationOrTraceOptions !== void 0) {
|
|
if (Is.boolean(sendNotificationOrTraceOptions)) {
|
|
_sendNotification = sendNotificationOrTraceOptions;
|
|
}
|
|
else {
|
|
_sendNotification = sendNotificationOrTraceOptions.sendNotification || false;
|
|
_traceFormat = sendNotificationOrTraceOptions.traceFormat || TraceFormat.Text;
|
|
}
|
|
}
|
|
trace = _value;
|
|
traceFormat = _traceFormat;
|
|
if (trace === Trace.Off) {
|
|
tracer = undefined;
|
|
}
|
|
else {
|
|
tracer = _tracer;
|
|
}
|
|
if (_sendNotification && !isClosed() && !isDisposed()) {
|
|
connection.sendNotification(SetTraceNotification.type, { value: Trace.toString(_value) });
|
|
}
|
|
},
|
|
onError: errorEmitter.event,
|
|
onClose: closeEmitter.event,
|
|
onUnhandledNotification: unhandledNotificationEmitter.event,
|
|
onDispose: disposeEmitter.event,
|
|
dispose: () => {
|
|
if (isDisposed()) {
|
|
return;
|
|
}
|
|
state = ConnectionState.Disposed;
|
|
disposeEmitter.fire(undefined);
|
|
let error = new Error('Connection got disposed.');
|
|
Object.keys(responsePromises).forEach((key) => {
|
|
responsePromises[key].reject(error);
|
|
});
|
|
responsePromises = Object.create(null);
|
|
requestTokens = Object.create(null);
|
|
messageQueue = new linkedMap_1.LinkedMap();
|
|
// Test for backwards compatibility
|
|
if (Is.func(messageWriter.dispose)) {
|
|
messageWriter.dispose();
|
|
}
|
|
if (Is.func(messageReader.dispose)) {
|
|
messageReader.dispose();
|
|
}
|
|
},
|
|
listen: () => {
|
|
throwIfClosedOrDisposed();
|
|
throwIfListening();
|
|
state = ConnectionState.Listening;
|
|
messageReader.listen(callback);
|
|
},
|
|
inspect: () => {
|
|
console.log("inspect");
|
|
}
|
|
};
|
|
connection.onNotification(LogTraceNotification.type, (params) => {
|
|
if (trace === Trace.Off || !tracer) {
|
|
return;
|
|
}
|
|
tracer.log(params.message, trace === Trace.Verbose ? params.verbose : undefined);
|
|
});
|
|
return connection;
|
|
}
|
|
function isMessageReader(value) {
|
|
return value.listen !== void 0 && value.read === void 0;
|
|
}
|
|
function isMessageWriter(value) {
|
|
return value.write !== void 0 && value.end === void 0;
|
|
}
|
|
function createMessageConnection(input, output, logger, strategy) {
|
|
if (!logger) {
|
|
logger = exports.NullLogger;
|
|
}
|
|
let reader = isMessageReader(input) ? input : new messageReader_1.StreamMessageReader(input);
|
|
let writer = isMessageWriter(output) ? output : new messageWriter_1.StreamMessageWriter(output);
|
|
return _createMessageConnection(reader, writer, logger, strategy);
|
|
}
|
|
exports.createMessageConnection = createMessageConnection;
|
|
|
|
|
|
/***/ }),
|
|
/* 151 */
|
|
/***/ (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 });
|
|
function boolean(value) {
|
|
return value === true || value === false;
|
|
}
|
|
exports.boolean = boolean;
|
|
function string(value) {
|
|
return typeof value === 'string' || value instanceof String;
|
|
}
|
|
exports.string = string;
|
|
function number(value) {
|
|
return typeof value === 'number' || value instanceof Number;
|
|
}
|
|
exports.number = number;
|
|
function error(value) {
|
|
return value instanceof Error;
|
|
}
|
|
exports.error = error;
|
|
function func(value) {
|
|
return typeof value === 'function';
|
|
}
|
|
exports.func = func;
|
|
function array(value) {
|
|
return Array.isArray(value);
|
|
}
|
|
exports.array = array;
|
|
function stringArray(value) {
|
|
return array(value) && value.every(elem => string(elem));
|
|
}
|
|
exports.stringArray = stringArray;
|
|
|
|
|
|
/***/ }),
|
|
/* 152 */
|
|
/***/ (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 is = __webpack_require__(151);
|
|
/**
|
|
* Predefined error codes.
|
|
*/
|
|
var ErrorCodes;
|
|
(function (ErrorCodes) {
|
|
// Defined by JSON RPC
|
|
ErrorCodes.ParseError = -32700;
|
|
ErrorCodes.InvalidRequest = -32600;
|
|
ErrorCodes.MethodNotFound = -32601;
|
|
ErrorCodes.InvalidParams = -32602;
|
|
ErrorCodes.InternalError = -32603;
|
|
ErrorCodes.serverErrorStart = -32099;
|
|
ErrorCodes.serverErrorEnd = -32000;
|
|
ErrorCodes.ServerNotInitialized = -32002;
|
|
ErrorCodes.UnknownErrorCode = -32001;
|
|
// Defined by the protocol.
|
|
ErrorCodes.RequestCancelled = -32800;
|
|
ErrorCodes.ContentModified = -32801;
|
|
// Defined by VSCode library.
|
|
ErrorCodes.MessageWriteError = 1;
|
|
ErrorCodes.MessageReadError = 2;
|
|
})(ErrorCodes = exports.ErrorCodes || (exports.ErrorCodes = {}));
|
|
/**
|
|
* An error object return in a response in case a request
|
|
* has failed.
|
|
*/
|
|
class ResponseError extends Error {
|
|
constructor(code, message, data) {
|
|
super(message);
|
|
this.code = is.number(code) ? code : ErrorCodes.UnknownErrorCode;
|
|
this.data = data;
|
|
Object.setPrototypeOf(this, ResponseError.prototype);
|
|
}
|
|
toJson() {
|
|
return {
|
|
code: this.code,
|
|
message: this.message,
|
|
data: this.data,
|
|
};
|
|
}
|
|
}
|
|
exports.ResponseError = ResponseError;
|
|
/**
|
|
* An abstract implementation of a MessageType.
|
|
*/
|
|
class AbstractMessageType {
|
|
constructor(_method, _numberOfParams) {
|
|
this._method = _method;
|
|
this._numberOfParams = _numberOfParams;
|
|
}
|
|
get method() {
|
|
return this._method;
|
|
}
|
|
get numberOfParams() {
|
|
return this._numberOfParams;
|
|
}
|
|
}
|
|
exports.AbstractMessageType = AbstractMessageType;
|
|
/**
|
|
* Classes to type request response pairs
|
|
*/
|
|
class RequestType0 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 0);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.RequestType0 = RequestType0;
|
|
class RequestType extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 1);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.RequestType = RequestType;
|
|
class RequestType1 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 1);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.RequestType1 = RequestType1;
|
|
class RequestType2 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 2);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.RequestType2 = RequestType2;
|
|
class RequestType3 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 3);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.RequestType3 = RequestType3;
|
|
class RequestType4 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 4);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.RequestType4 = RequestType4;
|
|
class RequestType5 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 5);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.RequestType5 = RequestType5;
|
|
class RequestType6 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 6);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.RequestType6 = RequestType6;
|
|
class RequestType7 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 7);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.RequestType7 = RequestType7;
|
|
class RequestType8 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 8);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.RequestType8 = RequestType8;
|
|
class RequestType9 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 9);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.RequestType9 = RequestType9;
|
|
class NotificationType extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 1);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.NotificationType = NotificationType;
|
|
class NotificationType0 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 0);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.NotificationType0 = NotificationType0;
|
|
class NotificationType1 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 1);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.NotificationType1 = NotificationType1;
|
|
class NotificationType2 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 2);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.NotificationType2 = NotificationType2;
|
|
class NotificationType3 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 3);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.NotificationType3 = NotificationType3;
|
|
class NotificationType4 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 4);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.NotificationType4 = NotificationType4;
|
|
class NotificationType5 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 5);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.NotificationType5 = NotificationType5;
|
|
class NotificationType6 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 6);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.NotificationType6 = NotificationType6;
|
|
class NotificationType7 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 7);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.NotificationType7 = NotificationType7;
|
|
class NotificationType8 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 8);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.NotificationType8 = NotificationType8;
|
|
class NotificationType9 extends AbstractMessageType {
|
|
constructor(method) {
|
|
super(method, 9);
|
|
this._ = undefined;
|
|
}
|
|
}
|
|
exports.NotificationType9 = NotificationType9;
|
|
/**
|
|
* Tests if the given message is a request message
|
|
*/
|
|
function isRequestMessage(message) {
|
|
let candidate = message;
|
|
return candidate && is.string(candidate.method) && (is.string(candidate.id) || is.number(candidate.id));
|
|
}
|
|
exports.isRequestMessage = isRequestMessage;
|
|
/**
|
|
* Tests if the given message is a notification message
|
|
*/
|
|
function isNotificationMessage(message) {
|
|
let candidate = message;
|
|
return candidate && is.string(candidate.method) && message.id === void 0;
|
|
}
|
|
exports.isNotificationMessage = isNotificationMessage;
|
|
/**
|
|
* Tests if the given message is a response message
|
|
*/
|
|
function isResponseMessage(message) {
|
|
let candidate = message;
|
|
return candidate && (candidate.result !== void 0 || !!candidate.error) && (is.string(candidate.id) || is.number(candidate.id) || candidate.id === null);
|
|
}
|
|
exports.isResponseMessage = isResponseMessage;
|
|
|
|
|
|
/***/ }),
|
|
/* 153 */
|
|
/***/ (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 events_1 = __webpack_require__(154);
|
|
const Is = __webpack_require__(151);
|
|
let DefaultSize = 8192;
|
|
let CR = Buffer.from('\r', 'ascii')[0];
|
|
let LF = Buffer.from('\n', 'ascii')[0];
|
|
let CRLF = '\r\n';
|
|
class MessageBuffer {
|
|
constructor(encoding = 'utf8') {
|
|
this.encoding = encoding;
|
|
this.index = 0;
|
|
this.buffer = Buffer.allocUnsafe(DefaultSize);
|
|
}
|
|
append(chunk) {
|
|
var toAppend = chunk;
|
|
if (typeof (chunk) === 'string') {
|
|
var str = chunk;
|
|
var bufferLen = Buffer.byteLength(str, this.encoding);
|
|
toAppend = Buffer.allocUnsafe(bufferLen);
|
|
toAppend.write(str, 0, bufferLen, this.encoding);
|
|
}
|
|
if (this.buffer.length - this.index >= toAppend.length) {
|
|
toAppend.copy(this.buffer, this.index, 0, toAppend.length);
|
|
}
|
|
else {
|
|
var newSize = (Math.ceil((this.index + toAppend.length) / DefaultSize) + 1) * DefaultSize;
|
|
if (this.index === 0) {
|
|
this.buffer = Buffer.allocUnsafe(newSize);
|
|
toAppend.copy(this.buffer, 0, 0, toAppend.length);
|
|
}
|
|
else {
|
|
this.buffer = Buffer.concat([this.buffer.slice(0, this.index), toAppend], newSize);
|
|
}
|
|
}
|
|
this.index += toAppend.length;
|
|
}
|
|
tryReadHeaders() {
|
|
let result = undefined;
|
|
let current = 0;
|
|
while (current + 3 < this.index && (this.buffer[current] !== CR || this.buffer[current + 1] !== LF || this.buffer[current + 2] !== CR || this.buffer[current + 3] !== LF)) {
|
|
current++;
|
|
}
|
|
// No header / body separator found (e.g CRLFCRLF)
|
|
if (current + 3 >= this.index) {
|
|
return result;
|
|
}
|
|
result = Object.create(null);
|
|
let headers = this.buffer.toString('ascii', 0, current).split(CRLF);
|
|
headers.forEach((header) => {
|
|
let index = header.indexOf(':');
|
|
if (index === -1) {
|
|
throw new Error('Message header must separate key and value using :');
|
|
}
|
|
let key = header.substr(0, index);
|
|
let value = header.substr(index + 1).trim();
|
|
result[key] = value;
|
|
});
|
|
let nextStart = current + 4;
|
|
this.buffer = this.buffer.slice(nextStart);
|
|
this.index = this.index - nextStart;
|
|
return result;
|
|
}
|
|
tryReadContent(length) {
|
|
if (this.index < length) {
|
|
return null;
|
|
}
|
|
let result = this.buffer.toString(this.encoding, 0, length);
|
|
let nextStart = length;
|
|
this.buffer.copy(this.buffer, 0, nextStart);
|
|
this.index = this.index - nextStart;
|
|
return result;
|
|
}
|
|
get numberOfBytes() {
|
|
return this.index;
|
|
}
|
|
}
|
|
var MessageReader;
|
|
(function (MessageReader) {
|
|
function is(value) {
|
|
let candidate = value;
|
|
return candidate && Is.func(candidate.listen) && Is.func(candidate.dispose) &&
|
|
Is.func(candidate.onError) && Is.func(candidate.onClose) && Is.func(candidate.onPartialMessage);
|
|
}
|
|
MessageReader.is = is;
|
|
})(MessageReader = exports.MessageReader || (exports.MessageReader = {}));
|
|
class AbstractMessageReader {
|
|
constructor() {
|
|
this.errorEmitter = new events_1.Emitter();
|
|
this.closeEmitter = new events_1.Emitter();
|
|
this.partialMessageEmitter = new events_1.Emitter();
|
|
}
|
|
dispose() {
|
|
this.errorEmitter.dispose();
|
|
this.closeEmitter.dispose();
|
|
}
|
|
get onError() {
|
|
return this.errorEmitter.event;
|
|
}
|
|
fireError(error) {
|
|
this.errorEmitter.fire(this.asError(error));
|
|
}
|
|
get onClose() {
|
|
return this.closeEmitter.event;
|
|
}
|
|
fireClose() {
|
|
this.closeEmitter.fire(undefined);
|
|
}
|
|
get onPartialMessage() {
|
|
return this.partialMessageEmitter.event;
|
|
}
|
|
firePartialMessage(info) {
|
|
this.partialMessageEmitter.fire(info);
|
|
}
|
|
asError(error) {
|
|
if (error instanceof Error) {
|
|
return error;
|
|
}
|
|
else {
|
|
return new Error(`Reader received error. Reason: ${Is.string(error.message) ? error.message : 'unknown'}`);
|
|
}
|
|
}
|
|
}
|
|
exports.AbstractMessageReader = AbstractMessageReader;
|
|
class StreamMessageReader extends AbstractMessageReader {
|
|
constructor(readable, encoding = 'utf8') {
|
|
super();
|
|
this.readable = readable;
|
|
this.buffer = new MessageBuffer(encoding);
|
|
this._partialMessageTimeout = 10000;
|
|
}
|
|
set partialMessageTimeout(timeout) {
|
|
this._partialMessageTimeout = timeout;
|
|
}
|
|
get partialMessageTimeout() {
|
|
return this._partialMessageTimeout;
|
|
}
|
|
listen(callback) {
|
|
this.nextMessageLength = -1;
|
|
this.messageToken = 0;
|
|
this.partialMessageTimer = undefined;
|
|
this.callback = callback;
|
|
this.readable.on('data', (data) => {
|
|
this.onData(data);
|
|
});
|
|
this.readable.on('error', (error) => this.fireError(error));
|
|
this.readable.on('close', () => this.fireClose());
|
|
}
|
|
onData(data) {
|
|
this.buffer.append(data);
|
|
while (true) {
|
|
if (this.nextMessageLength === -1) {
|
|
let headers = this.buffer.tryReadHeaders();
|
|
if (!headers) {
|
|
return;
|
|
}
|
|
let contentLength = headers['Content-Length'];
|
|
if (!contentLength) {
|
|
throw new Error('Header must provide a Content-Length property.');
|
|
}
|
|
let length = parseInt(contentLength);
|
|
if (isNaN(length)) {
|
|
throw new Error('Content-Length value must be a number.');
|
|
}
|
|
this.nextMessageLength = length;
|
|
// Take the encoding form the header. For compatibility
|
|
// treat both utf-8 and utf8 as node utf8
|
|
}
|
|
var msg = this.buffer.tryReadContent(this.nextMessageLength);
|
|
if (msg === null) {
|
|
/** We haven't received the full message yet. */
|
|
this.setPartialMessageTimer();
|
|
return;
|
|
}
|
|
this.clearPartialMessageTimer();
|
|
this.nextMessageLength = -1;
|
|
this.messageToken++;
|
|
var json = JSON.parse(msg);
|
|
this.callback(json);
|
|
}
|
|
}
|
|
clearPartialMessageTimer() {
|
|
if (this.partialMessageTimer) {
|
|
clearTimeout(this.partialMessageTimer);
|
|
this.partialMessageTimer = undefined;
|
|
}
|
|
}
|
|
setPartialMessageTimer() {
|
|
this.clearPartialMessageTimer();
|
|
if (this._partialMessageTimeout <= 0) {
|
|
return;
|
|
}
|
|
this.partialMessageTimer = setTimeout((token, timeout) => {
|
|
this.partialMessageTimer = undefined;
|
|
if (token === this.messageToken) {
|
|
this.firePartialMessage({ messageToken: token, waitingTime: timeout });
|
|
this.setPartialMessageTimer();
|
|
}
|
|
}, this._partialMessageTimeout, this.messageToken, this._partialMessageTimeout);
|
|
}
|
|
}
|
|
exports.StreamMessageReader = StreamMessageReader;
|
|
class IPCMessageReader extends AbstractMessageReader {
|
|
constructor(process) {
|
|
super();
|
|
this.process = process;
|
|
let eventEmitter = this.process;
|
|
eventEmitter.on('error', (error) => this.fireError(error));
|
|
eventEmitter.on('close', () => this.fireClose());
|
|
}
|
|
listen(callback) {
|
|
this.process.on('message', callback);
|
|
}
|
|
}
|
|
exports.IPCMessageReader = IPCMessageReader;
|
|
class SocketMessageReader extends StreamMessageReader {
|
|
constructor(socket, encoding = 'utf-8') {
|
|
super(socket, encoding);
|
|
}
|
|
}
|
|
exports.SocketMessageReader = SocketMessageReader;
|
|
|
|
|
|
/***/ }),
|
|
/* 154 */
|
|
/***/ (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 });
|
|
var Disposable;
|
|
(function (Disposable) {
|
|
function create(func) {
|
|
return {
|
|
dispose: func
|
|
};
|
|
}
|
|
Disposable.create = create;
|
|
})(Disposable = exports.Disposable || (exports.Disposable = {}));
|
|
var Event;
|
|
(function (Event) {
|
|
const _disposable = { dispose() { } };
|
|
Event.None = function () { return _disposable; };
|
|
})(Event = exports.Event || (exports.Event = {}));
|
|
class CallbackList {
|
|
add(callback, context = null, bucket) {
|
|
if (!this._callbacks) {
|
|
this._callbacks = [];
|
|
this._contexts = [];
|
|
}
|
|
this._callbacks.push(callback);
|
|
this._contexts.push(context);
|
|
if (Array.isArray(bucket)) {
|
|
bucket.push({ dispose: () => this.remove(callback, context) });
|
|
}
|
|
}
|
|
remove(callback, context = null) {
|
|
if (!this._callbacks) {
|
|
return;
|
|
}
|
|
var foundCallbackWithDifferentContext = false;
|
|
for (var i = 0, len = this._callbacks.length; i < len; i++) {
|
|
if (this._callbacks[i] === callback) {
|
|
if (this._contexts[i] === context) {
|
|
// callback & context match => remove it
|
|
this._callbacks.splice(i, 1);
|
|
this._contexts.splice(i, 1);
|
|
return;
|
|
}
|
|
else {
|
|
foundCallbackWithDifferentContext = true;
|
|
}
|
|
}
|
|
}
|
|
if (foundCallbackWithDifferentContext) {
|
|
throw new Error('When adding a listener with a context, you should remove it with the same context');
|
|
}
|
|
}
|
|
invoke(...args) {
|
|
if (!this._callbacks) {
|
|
return [];
|
|
}
|
|
var ret = [], callbacks = this._callbacks.slice(0), contexts = this._contexts.slice(0);
|
|
for (var i = 0, len = callbacks.length; i < len; i++) {
|
|
try {
|
|
ret.push(callbacks[i].apply(contexts[i], args));
|
|
}
|
|
catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
isEmpty() {
|
|
return !this._callbacks || this._callbacks.length === 0;
|
|
}
|
|
dispose() {
|
|
this._callbacks = undefined;
|
|
this._contexts = undefined;
|
|
}
|
|
}
|
|
class Emitter {
|
|
constructor(_options) {
|
|
this._options = _options;
|
|
}
|
|
/**
|
|
* For the public to allow to subscribe
|
|
* to events from this Emitter
|
|
*/
|
|
get event() {
|
|
if (!this._event) {
|
|
this._event = (listener, thisArgs, disposables) => {
|
|
if (!this._callbacks) {
|
|
this._callbacks = new CallbackList();
|
|
}
|
|
if (this._options && this._options.onFirstListenerAdd && this._callbacks.isEmpty()) {
|
|
this._options.onFirstListenerAdd(this);
|
|
}
|
|
this._callbacks.add(listener, thisArgs);
|
|
let result;
|
|
result = {
|
|
dispose: () => {
|
|
this._callbacks.remove(listener, thisArgs);
|
|
result.dispose = Emitter._noop;
|
|
if (this._options && this._options.onLastListenerRemove && this._callbacks.isEmpty()) {
|
|
this._options.onLastListenerRemove(this);
|
|
}
|
|
}
|
|
};
|
|
if (Array.isArray(disposables)) {
|
|
disposables.push(result);
|
|
}
|
|
return result;
|
|
};
|
|
}
|
|
return this._event;
|
|
}
|
|
/**
|
|
* To be kept private to fire an event to
|
|
* subscribers
|
|
*/
|
|
fire(event) {
|
|
if (this._callbacks) {
|
|
this._callbacks.invoke.call(this._callbacks, event);
|
|
}
|
|
}
|
|
dispose() {
|
|
if (this._callbacks) {
|
|
this._callbacks.dispose();
|
|
this._callbacks = undefined;
|
|
}
|
|
}
|
|
}
|
|
Emitter._noop = function () { };
|
|
exports.Emitter = Emitter;
|
|
|
|
|
|
/***/ }),
|
|
/* 155 */
|
|
/***/ (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 events_1 = __webpack_require__(154);
|
|
const Is = __webpack_require__(151);
|
|
let ContentLength = 'Content-Length: ';
|
|
let CRLF = '\r\n';
|
|
var MessageWriter;
|
|
(function (MessageWriter) {
|
|
function is(value) {
|
|
let candidate = value;
|
|
return candidate && Is.func(candidate.dispose) && Is.func(candidate.onClose) &&
|
|
Is.func(candidate.onError) && Is.func(candidate.write);
|
|
}
|
|
MessageWriter.is = is;
|
|
})(MessageWriter = exports.MessageWriter || (exports.MessageWriter = {}));
|
|
class AbstractMessageWriter {
|
|
constructor() {
|
|
this.errorEmitter = new events_1.Emitter();
|
|
this.closeEmitter = new events_1.Emitter();
|
|
}
|
|
dispose() {
|
|
this.errorEmitter.dispose();
|
|
this.closeEmitter.dispose();
|
|
}
|
|
get onError() {
|
|
return this.errorEmitter.event;
|
|
}
|
|
fireError(error, message, count) {
|
|
this.errorEmitter.fire([this.asError(error), message, count]);
|
|
}
|
|
get onClose() {
|
|
return this.closeEmitter.event;
|
|
}
|
|
fireClose() {
|
|
this.closeEmitter.fire(undefined);
|
|
}
|
|
asError(error) {
|
|
if (error instanceof Error) {
|
|
return error;
|
|
}
|
|
else {
|
|
return new Error(`Writer received error. Reason: ${Is.string(error.message) ? error.message : 'unknown'}`);
|
|
}
|
|
}
|
|
}
|
|
exports.AbstractMessageWriter = AbstractMessageWriter;
|
|
class StreamMessageWriter extends AbstractMessageWriter {
|
|
constructor(writable, encoding = 'utf8') {
|
|
super();
|
|
this.writable = writable;
|
|
this.encoding = encoding;
|
|
this.errorCount = 0;
|
|
this.writable.on('error', (error) => this.fireError(error));
|
|
this.writable.on('close', () => this.fireClose());
|
|
}
|
|
write(msg) {
|
|
let json = JSON.stringify(msg);
|
|
let contentLength = Buffer.byteLength(json, this.encoding);
|
|
let headers = [
|
|
ContentLength, contentLength.toString(), CRLF,
|
|
CRLF
|
|
];
|
|
try {
|
|
// Header must be written in ASCII encoding
|
|
this.writable.write(headers.join(''), 'ascii');
|
|
// Now write the content. This can be written in any encoding
|
|
this.writable.write(json, this.encoding);
|
|
this.errorCount = 0;
|
|
}
|
|
catch (error) {
|
|
this.errorCount++;
|
|
this.fireError(error, msg, this.errorCount);
|
|
}
|
|
}
|
|
}
|
|
exports.StreamMessageWriter = StreamMessageWriter;
|
|
class IPCMessageWriter extends AbstractMessageWriter {
|
|
constructor(process) {
|
|
super();
|
|
this.process = process;
|
|
this.errorCount = 0;
|
|
this.queue = [];
|
|
this.sending = false;
|
|
let eventEmitter = this.process;
|
|
eventEmitter.on('error', (error) => this.fireError(error));
|
|
eventEmitter.on('close', () => this.fireClose);
|
|
}
|
|
write(msg) {
|
|
if (!this.sending && this.queue.length === 0) {
|
|
// See https://github.com/nodejs/node/issues/7657
|
|
this.doWriteMessage(msg);
|
|
}
|
|
else {
|
|
this.queue.push(msg);
|
|
}
|
|
}
|
|
doWriteMessage(msg) {
|
|
try {
|
|
if (this.process.send) {
|
|
this.sending = true;
|
|
this.process.send(msg, undefined, undefined, (error) => {
|
|
this.sending = false;
|
|
if (error) {
|
|
this.errorCount++;
|
|
this.fireError(error, msg, this.errorCount);
|
|
}
|
|
else {
|
|
this.errorCount = 0;
|
|
}
|
|
if (this.queue.length > 0) {
|
|
this.doWriteMessage(this.queue.shift());
|
|
}
|
|
});
|
|
}
|
|
}
|
|
catch (error) {
|
|
this.errorCount++;
|
|
this.fireError(error, msg, this.errorCount);
|
|
}
|
|
}
|
|
}
|
|
exports.IPCMessageWriter = IPCMessageWriter;
|
|
class SocketMessageWriter extends AbstractMessageWriter {
|
|
constructor(socket, encoding = 'utf8') {
|
|
super();
|
|
this.socket = socket;
|
|
this.queue = [];
|
|
this.sending = false;
|
|
this.encoding = encoding;
|
|
this.errorCount = 0;
|
|
this.socket.on('error', (error) => this.fireError(error));
|
|
this.socket.on('close', () => this.fireClose());
|
|
}
|
|
dispose() {
|
|
super.dispose();
|
|
this.socket.destroy();
|
|
}
|
|
write(msg) {
|
|
if (!this.sending && this.queue.length === 0) {
|
|
// See https://github.com/nodejs/node/issues/7657
|
|
this.doWriteMessage(msg);
|
|
}
|
|
else {
|
|
this.queue.push(msg);
|
|
}
|
|
}
|
|
doWriteMessage(msg) {
|
|
let json = JSON.stringify(msg);
|
|
let contentLength = Buffer.byteLength(json, this.encoding);
|
|
let headers = [
|
|
ContentLength, contentLength.toString(), CRLF,
|
|
CRLF
|
|
];
|
|
try {
|
|
// Header must be written in ASCII encoding
|
|
this.sending = true;
|
|
this.socket.write(headers.join(''), 'ascii', (error) => {
|
|
if (error) {
|
|
this.handleError(error, msg);
|
|
}
|
|
try {
|
|
// Now write the content. This can be written in any encoding
|
|
this.socket.write(json, this.encoding, (error) => {
|
|
this.sending = false;
|
|
if (error) {
|
|
this.handleError(error, msg);
|
|
}
|
|
else {
|
|
this.errorCount = 0;
|
|
}
|
|
if (this.queue.length > 0) {
|
|
this.doWriteMessage(this.queue.shift());
|
|
}
|
|
});
|
|
}
|
|
catch (error) {
|
|
this.handleError(error, msg);
|
|
}
|
|
});
|
|
}
|
|
catch (error) {
|
|
this.handleError(error, msg);
|
|
}
|
|
}
|
|
handleError(error, msg) {
|
|
this.errorCount++;
|
|
this.fireError(error, msg, this.errorCount);
|
|
}
|
|
}
|
|
exports.SocketMessageWriter = SocketMessageWriter;
|
|
|
|
|
|
/***/ }),
|
|
/* 156 */
|
|
/***/ (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 events_1 = __webpack_require__(154);
|
|
const Is = __webpack_require__(151);
|
|
var CancellationToken;
|
|
(function (CancellationToken) {
|
|
CancellationToken.None = Object.freeze({
|
|
isCancellationRequested: false,
|
|
onCancellationRequested: events_1.Event.None
|
|
});
|
|
CancellationToken.Cancelled = Object.freeze({
|
|
isCancellationRequested: true,
|
|
onCancellationRequested: events_1.Event.None
|
|
});
|
|
function is(value) {
|
|
let candidate = value;
|
|
return candidate && (candidate === CancellationToken.None
|
|
|| candidate === CancellationToken.Cancelled
|
|
|| (Is.boolean(candidate.isCancellationRequested) && !!candidate.onCancellationRequested));
|
|
}
|
|
CancellationToken.is = is;
|
|
})(CancellationToken = exports.CancellationToken || (exports.CancellationToken = {}));
|
|
const shortcutEvent = Object.freeze(function (callback, context) {
|
|
let handle = setTimeout(callback.bind(context), 0);
|
|
return { dispose() { clearTimeout(handle); } };
|
|
});
|
|
class MutableToken {
|
|
constructor() {
|
|
this._isCancelled = false;
|
|
}
|
|
cancel() {
|
|
if (!this._isCancelled) {
|
|
this._isCancelled = true;
|
|
if (this._emitter) {
|
|
this._emitter.fire(undefined);
|
|
this.dispose();
|
|
}
|
|
}
|
|
}
|
|
get isCancellationRequested() {
|
|
return this._isCancelled;
|
|
}
|
|
get onCancellationRequested() {
|
|
if (this._isCancelled) {
|
|
return shortcutEvent;
|
|
}
|
|
if (!this._emitter) {
|
|
this._emitter = new events_1.Emitter();
|
|
}
|
|
return this._emitter.event;
|
|
}
|
|
dispose() {
|
|
if (this._emitter) {
|
|
this._emitter.dispose();
|
|
this._emitter = undefined;
|
|
}
|
|
}
|
|
}
|
|
class CancellationTokenSource {
|
|
get token() {
|
|
if (!this._token) {
|
|
// be lazy and create the token only when
|
|
// actually needed
|
|
this._token = new MutableToken();
|
|
}
|
|
return this._token;
|
|
}
|
|
cancel() {
|
|
if (!this._token) {
|
|
// save an object by returning the default
|
|
// cancelled token when cancellation happens
|
|
// before someone asks for the token
|
|
this._token = CancellationToken.Cancelled;
|
|
}
|
|
else {
|
|
this._token.cancel();
|
|
}
|
|
}
|
|
dispose() {
|
|
if (!this._token) {
|
|
// ensure to initialize with an empty token if we had none
|
|
this._token = CancellationToken.None;
|
|
}
|
|
else if (this._token instanceof MutableToken) {
|
|
// actually dispose
|
|
this._token.dispose();
|
|
}
|
|
}
|
|
}
|
|
exports.CancellationTokenSource = CancellationTokenSource;
|
|
|
|
|
|
/***/ }),
|
|
/* 157 */
|
|
/***/ (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 });
|
|
var Touch;
|
|
(function (Touch) {
|
|
Touch.None = 0;
|
|
Touch.First = 1;
|
|
Touch.Last = 2;
|
|
})(Touch = exports.Touch || (exports.Touch = {}));
|
|
class LinkedMap {
|
|
constructor() {
|
|
this._map = new Map();
|
|
this._head = undefined;
|
|
this._tail = undefined;
|
|
this._size = 0;
|
|
}
|
|
clear() {
|
|
this._map.clear();
|
|
this._head = undefined;
|
|
this._tail = undefined;
|
|
this._size = 0;
|
|
}
|
|
isEmpty() {
|
|
return !this._head && !this._tail;
|
|
}
|
|
get size() {
|
|
return this._size;
|
|
}
|
|
has(key) {
|
|
return this._map.has(key);
|
|
}
|
|
get(key) {
|
|
const item = this._map.get(key);
|
|
if (!item) {
|
|
return undefined;
|
|
}
|
|
return item.value;
|
|
}
|
|
set(key, value, touch = Touch.None) {
|
|
let item = this._map.get(key);
|
|
if (item) {
|
|
item.value = value;
|
|
if (touch !== Touch.None) {
|
|
this.touch(item, touch);
|
|
}
|
|
}
|
|
else {
|
|
item = { key, value, next: undefined, previous: undefined };
|
|
switch (touch) {
|
|
case Touch.None:
|
|
this.addItemLast(item);
|
|
break;
|
|
case Touch.First:
|
|
this.addItemFirst(item);
|
|
break;
|
|
case Touch.Last:
|
|
this.addItemLast(item);
|
|
break;
|
|
default:
|
|
this.addItemLast(item);
|
|
break;
|
|
}
|
|
this._map.set(key, item);
|
|
this._size++;
|
|
}
|
|
}
|
|
delete(key) {
|
|
const item = this._map.get(key);
|
|
if (!item) {
|
|
return false;
|
|
}
|
|
this._map.delete(key);
|
|
this.removeItem(item);
|
|
this._size--;
|
|
return true;
|
|
}
|
|
shift() {
|
|
if (!this._head && !this._tail) {
|
|
return undefined;
|
|
}
|
|
if (!this._head || !this._tail) {
|
|
throw new Error('Invalid list');
|
|
}
|
|
const item = this._head;
|
|
this._map.delete(item.key);
|
|
this.removeItem(item);
|
|
this._size--;
|
|
return item.value;
|
|
}
|
|
forEach(callbackfn, thisArg) {
|
|
let current = this._head;
|
|
while (current) {
|
|
if (thisArg) {
|
|
callbackfn.bind(thisArg)(current.value, current.key, this);
|
|
}
|
|
else {
|
|
callbackfn(current.value, current.key, this);
|
|
}
|
|
current = current.next;
|
|
}
|
|
}
|
|
forEachReverse(callbackfn, thisArg) {
|
|
let current = this._tail;
|
|
while (current) {
|
|
if (thisArg) {
|
|
callbackfn.bind(thisArg)(current.value, current.key, this);
|
|
}
|
|
else {
|
|
callbackfn(current.value, current.key, this);
|
|
}
|
|
current = current.previous;
|
|
}
|
|
}
|
|
values() {
|
|
let result = [];
|
|
let current = this._head;
|
|
while (current) {
|
|
result.push(current.value);
|
|
current = current.next;
|
|
}
|
|
return result;
|
|
}
|
|
keys() {
|
|
let result = [];
|
|
let current = this._head;
|
|
while (current) {
|
|
result.push(current.key);
|
|
current = current.next;
|
|
}
|
|
return result;
|
|
}
|
|
/* JSON RPC run on es5 which has no Symbol.iterator
|
|
public keys(): IterableIterator<K> {
|
|
let current = this._head;
|
|
let iterator: IterableIterator<K> = {
|
|
[Symbol.iterator]() {
|
|
return iterator;
|
|
},
|
|
next():IteratorResult<K> {
|
|
if (current) {
|
|
let result = { value: current.key, done: false };
|
|
current = current.next;
|
|
return result;
|
|
} else {
|
|
return { value: undefined, done: true };
|
|
}
|
|
}
|
|
};
|
|
return iterator;
|
|
}
|
|
|
|
public values(): IterableIterator<V> {
|
|
let current = this._head;
|
|
let iterator: IterableIterator<V> = {
|
|
[Symbol.iterator]() {
|
|
return iterator;
|
|
},
|
|
next():IteratorResult<V> {
|
|
if (current) {
|
|
let result = { value: current.value, done: false };
|
|
current = current.next;
|
|
return result;
|
|
} else {
|
|
return { value: undefined, done: true };
|
|
}
|
|
}
|
|
};
|
|
return iterator;
|
|
}
|
|
*/
|
|
addItemFirst(item) {
|
|
// First time Insert
|
|
if (!this._head && !this._tail) {
|
|
this._tail = item;
|
|
}
|
|
else if (!this._head) {
|
|
throw new Error('Invalid list');
|
|
}
|
|
else {
|
|
item.next = this._head;
|
|
this._head.previous = item;
|
|
}
|
|
this._head = item;
|
|
}
|
|
addItemLast(item) {
|
|
// First time Insert
|
|
if (!this._head && !this._tail) {
|
|
this._head = item;
|
|
}
|
|
else if (!this._tail) {
|
|
throw new Error('Invalid list');
|
|
}
|
|
else {
|
|
item.previous = this._tail;
|
|
this._tail.next = item;
|
|
}
|
|
this._tail = item;
|
|
}
|
|
removeItem(item) {
|
|
if (item === this._head && item === this._tail) {
|
|
this._head = undefined;
|
|
this._tail = undefined;
|
|
}
|
|
else if (item === this._head) {
|
|
this._head = item.next;
|
|
}
|
|
else if (item === this._tail) {
|
|
this._tail = item.previous;
|
|
}
|
|
else {
|
|
const next = item.next;
|
|
const previous = item.previous;
|
|
if (!next || !previous) {
|
|
throw new Error('Invalid list');
|
|
}
|
|
next.previous = previous;
|
|
previous.next = next;
|
|
}
|
|
}
|
|
touch(item, touch) {
|
|
if (!this._head || !this._tail) {
|
|
throw new Error('Invalid list');
|
|
}
|
|
if ((touch !== Touch.First && touch !== Touch.Last)) {
|
|
return;
|
|
}
|
|
if (touch === Touch.First) {
|
|
if (item === this._head) {
|
|
return;
|
|
}
|
|
const next = item.next;
|
|
const previous = item.previous;
|
|
// Unlink the item
|
|
if (item === this._tail) {
|
|
// previous must be defined since item was not head but is tail
|
|
// So there are more than on item in the map
|
|
previous.next = undefined;
|
|
this._tail = previous;
|
|
}
|
|
else {
|
|
// Both next and previous are not undefined since item was neither head nor tail.
|
|
next.previous = previous;
|
|
previous.next = next;
|
|
}
|
|
// Insert the node at head
|
|
item.previous = undefined;
|
|
item.next = this._head;
|
|
this._head.previous = item;
|
|
this._head = item;
|
|
}
|
|
else if (touch === Touch.Last) {
|
|
if (item === this._tail) {
|
|
return;
|
|
}
|
|
const next = item.next;
|
|
const previous = item.previous;
|
|
// Unlink the item.
|
|
if (item === this._head) {
|
|
// next must be defined since item was not tail but is head
|
|
// So there are more than on item in the map
|
|
next.previous = undefined;
|
|
this._head = next;
|
|
}
|
|
else {
|
|
// Both next and previous are not undefined since item was neither head nor tail.
|
|
next.previous = previous;
|
|
previous.next = next;
|
|
}
|
|
item.next = undefined;
|
|
item.previous = this._tail;
|
|
this._tail.next = item;
|
|
this._tail = item;
|
|
}
|
|
}
|
|
}
|
|
exports.LinkedMap = LinkedMap;
|
|
|
|
|
|
/***/ }),
|
|
/* 158 */
|
|
/***/ (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 path_1 = __webpack_require__(57);
|
|
const os_1 = __webpack_require__(56);
|
|
const crypto_1 = __webpack_require__(159);
|
|
const net_1 = __webpack_require__(6);
|
|
const messageReader_1 = __webpack_require__(153);
|
|
const messageWriter_1 = __webpack_require__(155);
|
|
function generateRandomPipeName() {
|
|
const randomSuffix = crypto_1.randomBytes(21).toString('hex');
|
|
if (process.platform === 'win32') {
|
|
return `\\\\.\\pipe\\vscode-jsonrpc-${randomSuffix}-sock`;
|
|
}
|
|
else {
|
|
// Mac/Unix: use socket file
|
|
return path_1.join(os_1.tmpdir(), `vscode-${randomSuffix}.sock`);
|
|
}
|
|
}
|
|
exports.generateRandomPipeName = generateRandomPipeName;
|
|
function createClientPipeTransport(pipeName, encoding = 'utf-8') {
|
|
let connectResolve;
|
|
let connected = new Promise((resolve, _reject) => {
|
|
connectResolve = resolve;
|
|
});
|
|
return new Promise((resolve, reject) => {
|
|
let server = net_1.createServer((socket) => {
|
|
server.close();
|
|
connectResolve([
|
|
new messageReader_1.SocketMessageReader(socket, encoding),
|
|
new messageWriter_1.SocketMessageWriter(socket, encoding)
|
|
]);
|
|
});
|
|
server.on('error', reject);
|
|
server.listen(pipeName, () => {
|
|
server.removeListener('error', reject);
|
|
resolve({
|
|
onConnected: () => { return connected; }
|
|
});
|
|
});
|
|
});
|
|
}
|
|
exports.createClientPipeTransport = createClientPipeTransport;
|
|
function createServerPipeTransport(pipeName, encoding = 'utf-8') {
|
|
const socket = net_1.createConnection(pipeName);
|
|
return [
|
|
new messageReader_1.SocketMessageReader(socket, encoding),
|
|
new messageWriter_1.SocketMessageWriter(socket, encoding)
|
|
];
|
|
}
|
|
exports.createServerPipeTransport = createServerPipeTransport;
|
|
|
|
|
|
/***/ }),
|
|
/* 159 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("crypto");
|
|
|
|
/***/ }),
|
|
/* 160 */
|
|
/***/ (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 net_1 = __webpack_require__(6);
|
|
const messageReader_1 = __webpack_require__(153);
|
|
const messageWriter_1 = __webpack_require__(155);
|
|
function createClientSocketTransport(port, encoding = 'utf-8') {
|
|
let connectResolve;
|
|
let connected = new Promise((resolve, _reject) => {
|
|
connectResolve = resolve;
|
|
});
|
|
return new Promise((resolve, reject) => {
|
|
let server = net_1.createServer((socket) => {
|
|
server.close();
|
|
connectResolve([
|
|
new messageReader_1.SocketMessageReader(socket, encoding),
|
|
new messageWriter_1.SocketMessageWriter(socket, encoding)
|
|
]);
|
|
});
|
|
server.on('error', reject);
|
|
server.listen(port, '127.0.0.1', () => {
|
|
server.removeListener('error', reject);
|
|
resolve({
|
|
onConnected: () => { return connected; }
|
|
});
|
|
});
|
|
});
|
|
}
|
|
exports.createClientSocketTransport = createClientSocketTransport;
|
|
function createServerSocketTransport(port, encoding = 'utf-8') {
|
|
const socket = net_1.createConnection(port, '127.0.0.1');
|
|
return [
|
|
new messageReader_1.SocketMessageReader(socket, encoding),
|
|
new messageWriter_1.SocketMessageWriter(socket, encoding)
|
|
];
|
|
}
|
|
exports.createServerSocketTransport = createServerSocketTransport;
|
|
|
|
|
|
/***/ }),
|
|
/* 161 */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Position", function() { return Position; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Range", function() { return Range; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Location", function() { return Location; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LocationLink", function() { return LocationLink; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Color", function() { return Color; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ColorInformation", function() { return ColorInformation; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ColorPresentation", function() { return ColorPresentation; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FoldingRangeKind", function() { return FoldingRangeKind; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FoldingRange", function() { return FoldingRange; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DiagnosticRelatedInformation", function() { return DiagnosticRelatedInformation; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DiagnosticSeverity", function() { return DiagnosticSeverity; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DiagnosticTag", function() { return DiagnosticTag; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Diagnostic", function() { return Diagnostic; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Command", function() { return Command; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextEdit", function() { return TextEdit; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextDocumentEdit", function() { return TextDocumentEdit; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CreateFile", function() { return CreateFile; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RenameFile", function() { return RenameFile; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeleteFile", function() { return DeleteFile; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WorkspaceEdit", function() { return WorkspaceEdit; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WorkspaceChange", function() { return WorkspaceChange; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextDocumentIdentifier", function() { return TextDocumentIdentifier; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VersionedTextDocumentIdentifier", function() { return VersionedTextDocumentIdentifier; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextDocumentItem", function() { return TextDocumentItem; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MarkupKind", function() { return MarkupKind; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MarkupContent", function() { return MarkupContent; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompletionItemKind", function() { return CompletionItemKind; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InsertTextFormat", function() { return InsertTextFormat; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompletionItem", function() { return CompletionItem; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompletionList", function() { return CompletionList; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MarkedString", function() { return MarkedString; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Hover", function() { return Hover; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParameterInformation", function() { return ParameterInformation; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SignatureInformation", function() { return SignatureInformation; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DocumentHighlightKind", function() { return DocumentHighlightKind; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DocumentHighlight", function() { return DocumentHighlight; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SymbolKind", function() { return SymbolKind; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SymbolInformation", function() { return SymbolInformation; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DocumentSymbol", function() { return DocumentSymbol; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CodeActionKind", function() { return CodeActionKind; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CodeActionContext", function() { return CodeActionContext; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CodeAction", function() { return CodeAction; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CodeLens", function() { return CodeLens; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FormattingOptions", function() { return FormattingOptions; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DocumentLink", function() { return DocumentLink; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SelectionRange", function() { return SelectionRange; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EOL", function() { return EOL; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextDocument", function() { return TextDocument; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextDocumentSaveReason", function() { return TextDocumentSaveReason; });
|
|
/* --------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
* ------------------------------------------------------------------------------------------ */
|
|
|
|
/**
|
|
* The Position namespace provides helper functions to work with
|
|
* [Position](#Position) literals.
|
|
*/
|
|
var Position;
|
|
(function (Position) {
|
|
/**
|
|
* Creates a new Position literal from the given line and character.
|
|
* @param line The position's line.
|
|
* @param character The position's character.
|
|
*/
|
|
function create(line, character) {
|
|
return { line: line, character: character };
|
|
}
|
|
Position.create = create;
|
|
/**
|
|
* Checks whether the given liternal conforms to the [Position](#Position) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.objectLiteral(candidate) && Is.number(candidate.line) && Is.number(candidate.character);
|
|
}
|
|
Position.is = is;
|
|
})(Position || (Position = {}));
|
|
/**
|
|
* The Range namespace provides helper functions to work with
|
|
* [Range](#Range) literals.
|
|
*/
|
|
var Range;
|
|
(function (Range) {
|
|
function create(one, two, three, four) {
|
|
if (Is.number(one) && Is.number(two) && Is.number(three) && Is.number(four)) {
|
|
return { start: Position.create(one, two), end: Position.create(three, four) };
|
|
}
|
|
else if (Position.is(one) && Position.is(two)) {
|
|
return { start: one, end: two };
|
|
}
|
|
else {
|
|
throw new Error("Range#create called with invalid arguments[" + one + ", " + two + ", " + three + ", " + four + "]");
|
|
}
|
|
}
|
|
Range.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [Range](#Range) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.objectLiteral(candidate) && Position.is(candidate.start) && Position.is(candidate.end);
|
|
}
|
|
Range.is = is;
|
|
})(Range || (Range = {}));
|
|
/**
|
|
* The Location namespace provides helper functions to work with
|
|
* [Location](#Location) literals.
|
|
*/
|
|
var Location;
|
|
(function (Location) {
|
|
/**
|
|
* Creates a Location literal.
|
|
* @param uri The location's uri.
|
|
* @param range The location's range.
|
|
*/
|
|
function create(uri, range) {
|
|
return { uri: uri, range: range };
|
|
}
|
|
Location.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [Location](#Location) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.defined(candidate) && Range.is(candidate.range) && (Is.string(candidate.uri) || Is.undefined(candidate.uri));
|
|
}
|
|
Location.is = is;
|
|
})(Location || (Location = {}));
|
|
/**
|
|
* The LocationLink namespace provides helper functions to work with
|
|
* [LocationLink](#LocationLink) literals.
|
|
*/
|
|
var LocationLink;
|
|
(function (LocationLink) {
|
|
/**
|
|
* Creates a LocationLink literal.
|
|
* @param targetUri The definition's uri.
|
|
* @param targetRange The full range of the definition.
|
|
* @param targetSelectionRange The span of the symbol definition at the target.
|
|
* @param originSelectionRange The span of the symbol being defined in the originating source file.
|
|
*/
|
|
function create(targetUri, targetRange, targetSelectionRange, originSelectionRange) {
|
|
return { targetUri: targetUri, targetRange: targetRange, targetSelectionRange: targetSelectionRange, originSelectionRange: originSelectionRange };
|
|
}
|
|
LocationLink.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [LocationLink](#LocationLink) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.defined(candidate) && Range.is(candidate.targetRange) && Is.string(candidate.targetUri)
|
|
&& (Range.is(candidate.targetSelectionRange) || Is.undefined(candidate.targetSelectionRange))
|
|
&& (Range.is(candidate.originSelectionRange) || Is.undefined(candidate.originSelectionRange));
|
|
}
|
|
LocationLink.is = is;
|
|
})(LocationLink || (LocationLink = {}));
|
|
/**
|
|
* The Color namespace provides helper functions to work with
|
|
* [Color](#Color) literals.
|
|
*/
|
|
var Color;
|
|
(function (Color) {
|
|
/**
|
|
* Creates a new Color literal.
|
|
*/
|
|
function create(red, green, blue, alpha) {
|
|
return {
|
|
red: red,
|
|
green: green,
|
|
blue: blue,
|
|
alpha: alpha,
|
|
};
|
|
}
|
|
Color.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [Color](#Color) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.number(candidate.red)
|
|
&& Is.number(candidate.green)
|
|
&& Is.number(candidate.blue)
|
|
&& Is.number(candidate.alpha);
|
|
}
|
|
Color.is = is;
|
|
})(Color || (Color = {}));
|
|
/**
|
|
* The ColorInformation namespace provides helper functions to work with
|
|
* [ColorInformation](#ColorInformation) literals.
|
|
*/
|
|
var ColorInformation;
|
|
(function (ColorInformation) {
|
|
/**
|
|
* Creates a new ColorInformation literal.
|
|
*/
|
|
function create(range, color) {
|
|
return {
|
|
range: range,
|
|
color: color,
|
|
};
|
|
}
|
|
ColorInformation.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [ColorInformation](#ColorInformation) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Range.is(candidate.range) && Color.is(candidate.color);
|
|
}
|
|
ColorInformation.is = is;
|
|
})(ColorInformation || (ColorInformation = {}));
|
|
/**
|
|
* The Color namespace provides helper functions to work with
|
|
* [ColorPresentation](#ColorPresentation) literals.
|
|
*/
|
|
var ColorPresentation;
|
|
(function (ColorPresentation) {
|
|
/**
|
|
* Creates a new ColorInformation literal.
|
|
*/
|
|
function create(label, textEdit, additionalTextEdits) {
|
|
return {
|
|
label: label,
|
|
textEdit: textEdit,
|
|
additionalTextEdits: additionalTextEdits,
|
|
};
|
|
}
|
|
ColorPresentation.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [ColorInformation](#ColorInformation) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.string(candidate.label)
|
|
&& (Is.undefined(candidate.textEdit) || TextEdit.is(candidate))
|
|
&& (Is.undefined(candidate.additionalTextEdits) || Is.typedArray(candidate.additionalTextEdits, TextEdit.is));
|
|
}
|
|
ColorPresentation.is = is;
|
|
})(ColorPresentation || (ColorPresentation = {}));
|
|
/**
|
|
* Enum of known range kinds
|
|
*/
|
|
var FoldingRangeKind;
|
|
(function (FoldingRangeKind) {
|
|
/**
|
|
* Folding range for a comment
|
|
*/
|
|
FoldingRangeKind["Comment"] = "comment";
|
|
/**
|
|
* Folding range for a imports or includes
|
|
*/
|
|
FoldingRangeKind["Imports"] = "imports";
|
|
/**
|
|
* Folding range for a region (e.g. `#region`)
|
|
*/
|
|
FoldingRangeKind["Region"] = "region";
|
|
})(FoldingRangeKind || (FoldingRangeKind = {}));
|
|
/**
|
|
* The folding range namespace provides helper functions to work with
|
|
* [FoldingRange](#FoldingRange) literals.
|
|
*/
|
|
var FoldingRange;
|
|
(function (FoldingRange) {
|
|
/**
|
|
* Creates a new FoldingRange literal.
|
|
*/
|
|
function create(startLine, endLine, startCharacter, endCharacter, kind) {
|
|
var result = {
|
|
startLine: startLine,
|
|
endLine: endLine
|
|
};
|
|
if (Is.defined(startCharacter)) {
|
|
result.startCharacter = startCharacter;
|
|
}
|
|
if (Is.defined(endCharacter)) {
|
|
result.endCharacter = endCharacter;
|
|
}
|
|
if (Is.defined(kind)) {
|
|
result.kind = kind;
|
|
}
|
|
return result;
|
|
}
|
|
FoldingRange.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [FoldingRange](#FoldingRange) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.number(candidate.startLine) && Is.number(candidate.startLine)
|
|
&& (Is.undefined(candidate.startCharacter) || Is.number(candidate.startCharacter))
|
|
&& (Is.undefined(candidate.endCharacter) || Is.number(candidate.endCharacter))
|
|
&& (Is.undefined(candidate.kind) || Is.string(candidate.kind));
|
|
}
|
|
FoldingRange.is = is;
|
|
})(FoldingRange || (FoldingRange = {}));
|
|
/**
|
|
* The DiagnosticRelatedInformation namespace provides helper functions to work with
|
|
* [DiagnosticRelatedInformation](#DiagnosticRelatedInformation) literals.
|
|
*/
|
|
var DiagnosticRelatedInformation;
|
|
(function (DiagnosticRelatedInformation) {
|
|
/**
|
|
* Creates a new DiagnosticRelatedInformation literal.
|
|
*/
|
|
function create(location, message) {
|
|
return {
|
|
location: location,
|
|
message: message
|
|
};
|
|
}
|
|
DiagnosticRelatedInformation.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [DiagnosticRelatedInformation](#DiagnosticRelatedInformation) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.defined(candidate) && Location.is(candidate.location) && Is.string(candidate.message);
|
|
}
|
|
DiagnosticRelatedInformation.is = is;
|
|
})(DiagnosticRelatedInformation || (DiagnosticRelatedInformation = {}));
|
|
/**
|
|
* The diagnostic's severity.
|
|
*/
|
|
var DiagnosticSeverity;
|
|
(function (DiagnosticSeverity) {
|
|
/**
|
|
* Reports an error.
|
|
*/
|
|
DiagnosticSeverity.Error = 1;
|
|
/**
|
|
* Reports a warning.
|
|
*/
|
|
DiagnosticSeverity.Warning = 2;
|
|
/**
|
|
* Reports an information.
|
|
*/
|
|
DiagnosticSeverity.Information = 3;
|
|
/**
|
|
* Reports a hint.
|
|
*/
|
|
DiagnosticSeverity.Hint = 4;
|
|
})(DiagnosticSeverity || (DiagnosticSeverity = {}));
|
|
var DiagnosticTag;
|
|
(function (DiagnosticTag) {
|
|
/**
|
|
* Unused or unnecessary code.
|
|
*
|
|
* Clients are allowed to render diagnostics with this tag faded out instead of having
|
|
* an error squiggle.
|
|
*/
|
|
DiagnosticTag.Unnecessary = 1;
|
|
})(DiagnosticTag || (DiagnosticTag = {}));
|
|
/**
|
|
* The Diagnostic namespace provides helper functions to work with
|
|
* [Diagnostic](#Diagnostic) literals.
|
|
*/
|
|
var Diagnostic;
|
|
(function (Diagnostic) {
|
|
/**
|
|
* Creates a new Diagnostic literal.
|
|
*/
|
|
function create(range, message, severity, code, source, relatedInformation) {
|
|
var result = { range: range, message: message };
|
|
if (Is.defined(severity)) {
|
|
result.severity = severity;
|
|
}
|
|
if (Is.defined(code)) {
|
|
result.code = code;
|
|
}
|
|
if (Is.defined(source)) {
|
|
result.source = source;
|
|
}
|
|
if (Is.defined(relatedInformation)) {
|
|
result.relatedInformation = relatedInformation;
|
|
}
|
|
return result;
|
|
}
|
|
Diagnostic.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [Diagnostic](#Diagnostic) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.defined(candidate)
|
|
&& Range.is(candidate.range)
|
|
&& Is.string(candidate.message)
|
|
&& (Is.number(candidate.severity) || Is.undefined(candidate.severity))
|
|
&& (Is.number(candidate.code) || Is.string(candidate.code) || Is.undefined(candidate.code))
|
|
&& (Is.string(candidate.source) || Is.undefined(candidate.source))
|
|
&& (Is.undefined(candidate.relatedInformation) || Is.typedArray(candidate.relatedInformation, DiagnosticRelatedInformation.is));
|
|
}
|
|
Diagnostic.is = is;
|
|
})(Diagnostic || (Diagnostic = {}));
|
|
/**
|
|
* The Command namespace provides helper functions to work with
|
|
* [Command](#Command) literals.
|
|
*/
|
|
var Command;
|
|
(function (Command) {
|
|
/**
|
|
* Creates a new Command literal.
|
|
*/
|
|
function create(title, command) {
|
|
var args = [];
|
|
for (var _i = 2; _i < arguments.length; _i++) {
|
|
args[_i - 2] = arguments[_i];
|
|
}
|
|
var result = { title: title, command: command };
|
|
if (Is.defined(args) && args.length > 0) {
|
|
result.arguments = args;
|
|
}
|
|
return result;
|
|
}
|
|
Command.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [Command](#Command) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.defined(candidate) && Is.string(candidate.title) && Is.string(candidate.command);
|
|
}
|
|
Command.is = is;
|
|
})(Command || (Command = {}));
|
|
/**
|
|
* The TextEdit namespace provides helper function to create replace,
|
|
* insert and delete edits more easily.
|
|
*/
|
|
var TextEdit;
|
|
(function (TextEdit) {
|
|
/**
|
|
* Creates a replace text edit.
|
|
* @param range The range of text to be replaced.
|
|
* @param newText The new text.
|
|
*/
|
|
function replace(range, newText) {
|
|
return { range: range, newText: newText };
|
|
}
|
|
TextEdit.replace = replace;
|
|
/**
|
|
* Creates a insert text edit.
|
|
* @param position The position to insert the text at.
|
|
* @param newText The text to be inserted.
|
|
*/
|
|
function insert(position, newText) {
|
|
return { range: { start: position, end: position }, newText: newText };
|
|
}
|
|
TextEdit.insert = insert;
|
|
/**
|
|
* Creates a delete text edit.
|
|
* @param range The range of text to be deleted.
|
|
*/
|
|
function del(range) {
|
|
return { range: range, newText: '' };
|
|
}
|
|
TextEdit.del = del;
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.objectLiteral(candidate)
|
|
&& Is.string(candidate.newText)
|
|
&& Range.is(candidate.range);
|
|
}
|
|
TextEdit.is = is;
|
|
})(TextEdit || (TextEdit = {}));
|
|
/**
|
|
* The TextDocumentEdit namespace provides helper function to create
|
|
* an edit that manipulates a text document.
|
|
*/
|
|
var TextDocumentEdit;
|
|
(function (TextDocumentEdit) {
|
|
/**
|
|
* Creates a new `TextDocumentEdit`
|
|
*/
|
|
function create(textDocument, edits) {
|
|
return { textDocument: textDocument, edits: edits };
|
|
}
|
|
TextDocumentEdit.create = create;
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.defined(candidate)
|
|
&& VersionedTextDocumentIdentifier.is(candidate.textDocument)
|
|
&& Array.isArray(candidate.edits);
|
|
}
|
|
TextDocumentEdit.is = is;
|
|
})(TextDocumentEdit || (TextDocumentEdit = {}));
|
|
var CreateFile;
|
|
(function (CreateFile) {
|
|
function create(uri, options) {
|
|
var result = {
|
|
kind: 'create',
|
|
uri: uri
|
|
};
|
|
if (options !== void 0 && (options.overwrite !== void 0 || options.ignoreIfExists !== void 0)) {
|
|
result.options = options;
|
|
}
|
|
return result;
|
|
}
|
|
CreateFile.create = create;
|
|
function is(value) {
|
|
var candidate = value;
|
|
return candidate && candidate.kind === 'create' && Is.string(candidate.uri) &&
|
|
(candidate.options === void 0 ||
|
|
((candidate.options.overwrite === void 0 || Is.boolean(candidate.options.overwrite)) && (candidate.options.ignoreIfExists === void 0 || Is.boolean(candidate.options.ignoreIfExists))));
|
|
}
|
|
CreateFile.is = is;
|
|
})(CreateFile || (CreateFile = {}));
|
|
var RenameFile;
|
|
(function (RenameFile) {
|
|
function create(oldUri, newUri, options) {
|
|
var result = {
|
|
kind: 'rename',
|
|
oldUri: oldUri,
|
|
newUri: newUri
|
|
};
|
|
if (options !== void 0 && (options.overwrite !== void 0 || options.ignoreIfExists !== void 0)) {
|
|
result.options = options;
|
|
}
|
|
return result;
|
|
}
|
|
RenameFile.create = create;
|
|
function is(value) {
|
|
var candidate = value;
|
|
return candidate && candidate.kind === 'rename' && Is.string(candidate.oldUri) && Is.string(candidate.newUri) &&
|
|
(candidate.options === void 0 ||
|
|
((candidate.options.overwrite === void 0 || Is.boolean(candidate.options.overwrite)) && (candidate.options.ignoreIfExists === void 0 || Is.boolean(candidate.options.ignoreIfExists))));
|
|
}
|
|
RenameFile.is = is;
|
|
})(RenameFile || (RenameFile = {}));
|
|
var DeleteFile;
|
|
(function (DeleteFile) {
|
|
function create(uri, options) {
|
|
var result = {
|
|
kind: 'delete',
|
|
uri: uri
|
|
};
|
|
if (options !== void 0 && (options.recursive !== void 0 || options.ignoreIfNotExists !== void 0)) {
|
|
result.options = options;
|
|
}
|
|
return result;
|
|
}
|
|
DeleteFile.create = create;
|
|
function is(value) {
|
|
var candidate = value;
|
|
return candidate && candidate.kind === 'delete' && Is.string(candidate.uri) &&
|
|
(candidate.options === void 0 ||
|
|
((candidate.options.recursive === void 0 || Is.boolean(candidate.options.recursive)) && (candidate.options.ignoreIfNotExists === void 0 || Is.boolean(candidate.options.ignoreIfNotExists))));
|
|
}
|
|
DeleteFile.is = is;
|
|
})(DeleteFile || (DeleteFile = {}));
|
|
var WorkspaceEdit;
|
|
(function (WorkspaceEdit) {
|
|
function is(value) {
|
|
var candidate = value;
|
|
return candidate &&
|
|
(candidate.changes !== void 0 || candidate.documentChanges !== void 0) &&
|
|
(candidate.documentChanges === void 0 || candidate.documentChanges.every(function (change) {
|
|
if (Is.string(change.kind)) {
|
|
return CreateFile.is(change) || RenameFile.is(change) || DeleteFile.is(change);
|
|
}
|
|
else {
|
|
return TextDocumentEdit.is(change);
|
|
}
|
|
}));
|
|
}
|
|
WorkspaceEdit.is = is;
|
|
})(WorkspaceEdit || (WorkspaceEdit = {}));
|
|
var TextEditChangeImpl = /** @class */ (function () {
|
|
function TextEditChangeImpl(edits) {
|
|
this.edits = edits;
|
|
}
|
|
TextEditChangeImpl.prototype.insert = function (position, newText) {
|
|
this.edits.push(TextEdit.insert(position, newText));
|
|
};
|
|
TextEditChangeImpl.prototype.replace = function (range, newText) {
|
|
this.edits.push(TextEdit.replace(range, newText));
|
|
};
|
|
TextEditChangeImpl.prototype.delete = function (range) {
|
|
this.edits.push(TextEdit.del(range));
|
|
};
|
|
TextEditChangeImpl.prototype.add = function (edit) {
|
|
this.edits.push(edit);
|
|
};
|
|
TextEditChangeImpl.prototype.all = function () {
|
|
return this.edits;
|
|
};
|
|
TextEditChangeImpl.prototype.clear = function () {
|
|
this.edits.splice(0, this.edits.length);
|
|
};
|
|
return TextEditChangeImpl;
|
|
}());
|
|
/**
|
|
* A workspace change helps constructing changes to a workspace.
|
|
*/
|
|
var WorkspaceChange = /** @class */ (function () {
|
|
function WorkspaceChange(workspaceEdit) {
|
|
var _this = this;
|
|
this._textEditChanges = Object.create(null);
|
|
if (workspaceEdit) {
|
|
this._workspaceEdit = workspaceEdit;
|
|
if (workspaceEdit.documentChanges) {
|
|
workspaceEdit.documentChanges.forEach(function (change) {
|
|
if (TextDocumentEdit.is(change)) {
|
|
var textEditChange = new TextEditChangeImpl(change.edits);
|
|
_this._textEditChanges[change.textDocument.uri] = textEditChange;
|
|
}
|
|
});
|
|
}
|
|
else if (workspaceEdit.changes) {
|
|
Object.keys(workspaceEdit.changes).forEach(function (key) {
|
|
var textEditChange = new TextEditChangeImpl(workspaceEdit.changes[key]);
|
|
_this._textEditChanges[key] = textEditChange;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
Object.defineProperty(WorkspaceChange.prototype, "edit", {
|
|
/**
|
|
* Returns the underlying [WorkspaceEdit](#WorkspaceEdit) literal
|
|
* use to be returned from a workspace edit operation like rename.
|
|
*/
|
|
get: function () {
|
|
return this._workspaceEdit;
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
});
|
|
WorkspaceChange.prototype.getTextEditChange = function (key) {
|
|
if (VersionedTextDocumentIdentifier.is(key)) {
|
|
if (!this._workspaceEdit) {
|
|
this._workspaceEdit = {
|
|
documentChanges: []
|
|
};
|
|
}
|
|
if (!this._workspaceEdit.documentChanges) {
|
|
throw new Error('Workspace edit is not configured for document changes.');
|
|
}
|
|
var textDocument = key;
|
|
var result = this._textEditChanges[textDocument.uri];
|
|
if (!result) {
|
|
var edits = [];
|
|
var textDocumentEdit = {
|
|
textDocument: textDocument,
|
|
edits: edits
|
|
};
|
|
this._workspaceEdit.documentChanges.push(textDocumentEdit);
|
|
result = new TextEditChangeImpl(edits);
|
|
this._textEditChanges[textDocument.uri] = result;
|
|
}
|
|
return result;
|
|
}
|
|
else {
|
|
if (!this._workspaceEdit) {
|
|
this._workspaceEdit = {
|
|
changes: Object.create(null)
|
|
};
|
|
}
|
|
if (!this._workspaceEdit.changes) {
|
|
throw new Error('Workspace edit is not configured for normal text edit changes.');
|
|
}
|
|
var result = this._textEditChanges[key];
|
|
if (!result) {
|
|
var edits = [];
|
|
this._workspaceEdit.changes[key] = edits;
|
|
result = new TextEditChangeImpl(edits);
|
|
this._textEditChanges[key] = result;
|
|
}
|
|
return result;
|
|
}
|
|
};
|
|
WorkspaceChange.prototype.createFile = function (uri, options) {
|
|
this.checkDocumentChanges();
|
|
this._workspaceEdit.documentChanges.push(CreateFile.create(uri, options));
|
|
};
|
|
WorkspaceChange.prototype.renameFile = function (oldUri, newUri, options) {
|
|
this.checkDocumentChanges();
|
|
this._workspaceEdit.documentChanges.push(RenameFile.create(oldUri, newUri, options));
|
|
};
|
|
WorkspaceChange.prototype.deleteFile = function (uri, options) {
|
|
this.checkDocumentChanges();
|
|
this._workspaceEdit.documentChanges.push(DeleteFile.create(uri, options));
|
|
};
|
|
WorkspaceChange.prototype.checkDocumentChanges = function () {
|
|
if (!this._workspaceEdit || !this._workspaceEdit.documentChanges) {
|
|
throw new Error('Workspace edit is not configured for document changes.');
|
|
}
|
|
};
|
|
return WorkspaceChange;
|
|
}());
|
|
|
|
/**
|
|
* The TextDocumentIdentifier namespace provides helper functions to work with
|
|
* [TextDocumentIdentifier](#TextDocumentIdentifier) literals.
|
|
*/
|
|
var TextDocumentIdentifier;
|
|
(function (TextDocumentIdentifier) {
|
|
/**
|
|
* Creates a new TextDocumentIdentifier literal.
|
|
* @param uri The document's uri.
|
|
*/
|
|
function create(uri) {
|
|
return { uri: uri };
|
|
}
|
|
TextDocumentIdentifier.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [TextDocumentIdentifier](#TextDocumentIdentifier) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.defined(candidate) && Is.string(candidate.uri);
|
|
}
|
|
TextDocumentIdentifier.is = is;
|
|
})(TextDocumentIdentifier || (TextDocumentIdentifier = {}));
|
|
/**
|
|
* The VersionedTextDocumentIdentifier namespace provides helper functions to work with
|
|
* [VersionedTextDocumentIdentifier](#VersionedTextDocumentIdentifier) literals.
|
|
*/
|
|
var VersionedTextDocumentIdentifier;
|
|
(function (VersionedTextDocumentIdentifier) {
|
|
/**
|
|
* Creates a new VersionedTextDocumentIdentifier literal.
|
|
* @param uri The document's uri.
|
|
* @param uri The document's text.
|
|
*/
|
|
function create(uri, version) {
|
|
return { uri: uri, version: version };
|
|
}
|
|
VersionedTextDocumentIdentifier.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [VersionedTextDocumentIdentifier](#VersionedTextDocumentIdentifier) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.defined(candidate) && Is.string(candidate.uri) && (candidate.version === null || Is.number(candidate.version));
|
|
}
|
|
VersionedTextDocumentIdentifier.is = is;
|
|
})(VersionedTextDocumentIdentifier || (VersionedTextDocumentIdentifier = {}));
|
|
/**
|
|
* The TextDocumentItem namespace provides helper functions to work with
|
|
* [TextDocumentItem](#TextDocumentItem) literals.
|
|
*/
|
|
var TextDocumentItem;
|
|
(function (TextDocumentItem) {
|
|
/**
|
|
* Creates a new TextDocumentItem literal.
|
|
* @param uri The document's uri.
|
|
* @param languageId The document's language identifier.
|
|
* @param version The document's version number.
|
|
* @param text The document's text.
|
|
*/
|
|
function create(uri, languageId, version, text) {
|
|
return { uri: uri, languageId: languageId, version: version, text: text };
|
|
}
|
|
TextDocumentItem.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [TextDocumentItem](#TextDocumentItem) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.defined(candidate) && Is.string(candidate.uri) && Is.string(candidate.languageId) && Is.number(candidate.version) && Is.string(candidate.text);
|
|
}
|
|
TextDocumentItem.is = is;
|
|
})(TextDocumentItem || (TextDocumentItem = {}));
|
|
/**
|
|
* Describes the content type that a client supports in various
|
|
* result literals like `Hover`, `ParameterInfo` or `CompletionItem`.
|
|
*
|
|
* Please note that `MarkupKinds` must not start with a `$`. This kinds
|
|
* are reserved for internal usage.
|
|
*/
|
|
var MarkupKind;
|
|
(function (MarkupKind) {
|
|
/**
|
|
* Plain text is supported as a content format
|
|
*/
|
|
MarkupKind.PlainText = 'plaintext';
|
|
/**
|
|
* Markdown is supported as a content format
|
|
*/
|
|
MarkupKind.Markdown = 'markdown';
|
|
})(MarkupKind || (MarkupKind = {}));
|
|
(function (MarkupKind) {
|
|
/**
|
|
* Checks whether the given value is a value of the [MarkupKind](#MarkupKind) type.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return candidate === MarkupKind.PlainText || candidate === MarkupKind.Markdown;
|
|
}
|
|
MarkupKind.is = is;
|
|
})(MarkupKind || (MarkupKind = {}));
|
|
var MarkupContent;
|
|
(function (MarkupContent) {
|
|
/**
|
|
* Checks whether the given value conforms to the [MarkupContent](#MarkupContent) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.objectLiteral(value) && MarkupKind.is(candidate.kind) && Is.string(candidate.value);
|
|
}
|
|
MarkupContent.is = is;
|
|
})(MarkupContent || (MarkupContent = {}));
|
|
/**
|
|
* The kind of a completion entry.
|
|
*/
|
|
var CompletionItemKind;
|
|
(function (CompletionItemKind) {
|
|
CompletionItemKind.Text = 1;
|
|
CompletionItemKind.Method = 2;
|
|
CompletionItemKind.Function = 3;
|
|
CompletionItemKind.Constructor = 4;
|
|
CompletionItemKind.Field = 5;
|
|
CompletionItemKind.Variable = 6;
|
|
CompletionItemKind.Class = 7;
|
|
CompletionItemKind.Interface = 8;
|
|
CompletionItemKind.Module = 9;
|
|
CompletionItemKind.Property = 10;
|
|
CompletionItemKind.Unit = 11;
|
|
CompletionItemKind.Value = 12;
|
|
CompletionItemKind.Enum = 13;
|
|
CompletionItemKind.Keyword = 14;
|
|
CompletionItemKind.Snippet = 15;
|
|
CompletionItemKind.Color = 16;
|
|
CompletionItemKind.File = 17;
|
|
CompletionItemKind.Reference = 18;
|
|
CompletionItemKind.Folder = 19;
|
|
CompletionItemKind.EnumMember = 20;
|
|
CompletionItemKind.Constant = 21;
|
|
CompletionItemKind.Struct = 22;
|
|
CompletionItemKind.Event = 23;
|
|
CompletionItemKind.Operator = 24;
|
|
CompletionItemKind.TypeParameter = 25;
|
|
})(CompletionItemKind || (CompletionItemKind = {}));
|
|
/**
|
|
* Defines whether the insert text in a completion item should be interpreted as
|
|
* plain text or a snippet.
|
|
*/
|
|
var InsertTextFormat;
|
|
(function (InsertTextFormat) {
|
|
/**
|
|
* The primary text to be inserted is treated as a plain string.
|
|
*/
|
|
InsertTextFormat.PlainText = 1;
|
|
/**
|
|
* The primary text to be inserted is treated as a snippet.
|
|
*
|
|
* A snippet can define tab stops and placeholders with `$1`, `$2`
|
|
* and `${3:foo}`. `$0` defines the final tab stop, it defaults to
|
|
* the end of the snippet. Placeholders with equal identifiers are linked,
|
|
* that is typing in one will update others too.
|
|
*
|
|
* See also: https://github.com/Microsoft/vscode/blob/master/src/vs/editor/contrib/snippet/common/snippet.md
|
|
*/
|
|
InsertTextFormat.Snippet = 2;
|
|
})(InsertTextFormat || (InsertTextFormat = {}));
|
|
/**
|
|
* The CompletionItem namespace provides functions to deal with
|
|
* completion items.
|
|
*/
|
|
var CompletionItem;
|
|
(function (CompletionItem) {
|
|
/**
|
|
* Create a completion item and seed it with a label.
|
|
* @param label The completion item's label
|
|
*/
|
|
function create(label) {
|
|
return { label: label };
|
|
}
|
|
CompletionItem.create = create;
|
|
})(CompletionItem || (CompletionItem = {}));
|
|
/**
|
|
* The CompletionList namespace provides functions to deal with
|
|
* completion lists.
|
|
*/
|
|
var CompletionList;
|
|
(function (CompletionList) {
|
|
/**
|
|
* Creates a new completion list.
|
|
*
|
|
* @param items The completion items.
|
|
* @param isIncomplete The list is not complete.
|
|
*/
|
|
function create(items, isIncomplete) {
|
|
return { items: items ? items : [], isIncomplete: !!isIncomplete };
|
|
}
|
|
CompletionList.create = create;
|
|
})(CompletionList || (CompletionList = {}));
|
|
var MarkedString;
|
|
(function (MarkedString) {
|
|
/**
|
|
* Creates a marked string from plain text.
|
|
*
|
|
* @param plainText The plain text.
|
|
*/
|
|
function fromPlainText(plainText) {
|
|
return plainText.replace(/[\\`*_{}[\]()#+\-.!]/g, "\\$&"); // escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash
|
|
}
|
|
MarkedString.fromPlainText = fromPlainText;
|
|
/**
|
|
* Checks whether the given value conforms to the [MarkedString](#MarkedString) type.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.string(candidate) || (Is.objectLiteral(candidate) && Is.string(candidate.language) && Is.string(candidate.value));
|
|
}
|
|
MarkedString.is = is;
|
|
})(MarkedString || (MarkedString = {}));
|
|
var Hover;
|
|
(function (Hover) {
|
|
/**
|
|
* Checks whether the given value conforms to the [Hover](#Hover) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return !!candidate && Is.objectLiteral(candidate) && (MarkupContent.is(candidate.contents) ||
|
|
MarkedString.is(candidate.contents) ||
|
|
Is.typedArray(candidate.contents, MarkedString.is)) && (value.range === void 0 || Range.is(value.range));
|
|
}
|
|
Hover.is = is;
|
|
})(Hover || (Hover = {}));
|
|
/**
|
|
* The ParameterInformation namespace provides helper functions to work with
|
|
* [ParameterInformation](#ParameterInformation) literals.
|
|
*/
|
|
var ParameterInformation;
|
|
(function (ParameterInformation) {
|
|
/**
|
|
* Creates a new parameter information literal.
|
|
*
|
|
* @param label A label string.
|
|
* @param documentation A doc string.
|
|
*/
|
|
function create(label, documentation) {
|
|
return documentation ? { label: label, documentation: documentation } : { label: label };
|
|
}
|
|
ParameterInformation.create = create;
|
|
;
|
|
})(ParameterInformation || (ParameterInformation = {}));
|
|
/**
|
|
* The SignatureInformation namespace provides helper functions to work with
|
|
* [SignatureInformation](#SignatureInformation) literals.
|
|
*/
|
|
var SignatureInformation;
|
|
(function (SignatureInformation) {
|
|
function create(label, documentation) {
|
|
var parameters = [];
|
|
for (var _i = 2; _i < arguments.length; _i++) {
|
|
parameters[_i - 2] = arguments[_i];
|
|
}
|
|
var result = { label: label };
|
|
if (Is.defined(documentation)) {
|
|
result.documentation = documentation;
|
|
}
|
|
if (Is.defined(parameters)) {
|
|
result.parameters = parameters;
|
|
}
|
|
else {
|
|
result.parameters = [];
|
|
}
|
|
return result;
|
|
}
|
|
SignatureInformation.create = create;
|
|
})(SignatureInformation || (SignatureInformation = {}));
|
|
/**
|
|
* A document highlight kind.
|
|
*/
|
|
var DocumentHighlightKind;
|
|
(function (DocumentHighlightKind) {
|
|
/**
|
|
* A textual occurrence.
|
|
*/
|
|
DocumentHighlightKind.Text = 1;
|
|
/**
|
|
* Read-access of a symbol, like reading a variable.
|
|
*/
|
|
DocumentHighlightKind.Read = 2;
|
|
/**
|
|
* Write-access of a symbol, like writing to a variable.
|
|
*/
|
|
DocumentHighlightKind.Write = 3;
|
|
})(DocumentHighlightKind || (DocumentHighlightKind = {}));
|
|
/**
|
|
* DocumentHighlight namespace to provide helper functions to work with
|
|
* [DocumentHighlight](#DocumentHighlight) literals.
|
|
*/
|
|
var DocumentHighlight;
|
|
(function (DocumentHighlight) {
|
|
/**
|
|
* Create a DocumentHighlight object.
|
|
* @param range The range the highlight applies to.
|
|
*/
|
|
function create(range, kind) {
|
|
var result = { range: range };
|
|
if (Is.number(kind)) {
|
|
result.kind = kind;
|
|
}
|
|
return result;
|
|
}
|
|
DocumentHighlight.create = create;
|
|
})(DocumentHighlight || (DocumentHighlight = {}));
|
|
/**
|
|
* A symbol kind.
|
|
*/
|
|
var SymbolKind;
|
|
(function (SymbolKind) {
|
|
SymbolKind.File = 1;
|
|
SymbolKind.Module = 2;
|
|
SymbolKind.Namespace = 3;
|
|
SymbolKind.Package = 4;
|
|
SymbolKind.Class = 5;
|
|
SymbolKind.Method = 6;
|
|
SymbolKind.Property = 7;
|
|
SymbolKind.Field = 8;
|
|
SymbolKind.Constructor = 9;
|
|
SymbolKind.Enum = 10;
|
|
SymbolKind.Interface = 11;
|
|
SymbolKind.Function = 12;
|
|
SymbolKind.Variable = 13;
|
|
SymbolKind.Constant = 14;
|
|
SymbolKind.String = 15;
|
|
SymbolKind.Number = 16;
|
|
SymbolKind.Boolean = 17;
|
|
SymbolKind.Array = 18;
|
|
SymbolKind.Object = 19;
|
|
SymbolKind.Key = 20;
|
|
SymbolKind.Null = 21;
|
|
SymbolKind.EnumMember = 22;
|
|
SymbolKind.Struct = 23;
|
|
SymbolKind.Event = 24;
|
|
SymbolKind.Operator = 25;
|
|
SymbolKind.TypeParameter = 26;
|
|
})(SymbolKind || (SymbolKind = {}));
|
|
var SymbolInformation;
|
|
(function (SymbolInformation) {
|
|
/**
|
|
* Creates a new symbol information literal.
|
|
*
|
|
* @param name The name of the symbol.
|
|
* @param kind The kind of the symbol.
|
|
* @param range The range of the location of the symbol.
|
|
* @param uri The resource of the location of symbol, defaults to the current document.
|
|
* @param containerName The name of the symbol containing the symbol.
|
|
*/
|
|
function create(name, kind, range, uri, containerName) {
|
|
var result = {
|
|
name: name,
|
|
kind: kind,
|
|
location: { uri: uri, range: range }
|
|
};
|
|
if (containerName) {
|
|
result.containerName = containerName;
|
|
}
|
|
return result;
|
|
}
|
|
SymbolInformation.create = create;
|
|
})(SymbolInformation || (SymbolInformation = {}));
|
|
/**
|
|
* Represents programming constructs like variables, classes, interfaces etc.
|
|
* that appear in a document. Document symbols can be hierarchical and they
|
|
* have two ranges: one that encloses its definition and one that points to
|
|
* its most interesting range, e.g. the range of an identifier.
|
|
*/
|
|
var DocumentSymbol = /** @class */ (function () {
|
|
function DocumentSymbol() {
|
|
}
|
|
return DocumentSymbol;
|
|
}());
|
|
|
|
(function (DocumentSymbol) {
|
|
/**
|
|
* Creates a new symbol information literal.
|
|
*
|
|
* @param name The name of the symbol.
|
|
* @param detail The detail of the symbol.
|
|
* @param kind The kind of the symbol.
|
|
* @param range The range of the symbol.
|
|
* @param selectionRange The selectionRange of the symbol.
|
|
* @param children Children of the symbol.
|
|
*/
|
|
function create(name, detail, kind, range, selectionRange, children) {
|
|
var result = {
|
|
name: name,
|
|
detail: detail,
|
|
kind: kind,
|
|
range: range,
|
|
selectionRange: selectionRange
|
|
};
|
|
if (children !== void 0) {
|
|
result.children = children;
|
|
}
|
|
return result;
|
|
}
|
|
DocumentSymbol.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [DocumentSymbol](#DocumentSymbol) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return candidate &&
|
|
Is.string(candidate.name) && Is.number(candidate.kind) &&
|
|
Range.is(candidate.range) && Range.is(candidate.selectionRange) &&
|
|
(candidate.detail === void 0 || Is.string(candidate.detail)) &&
|
|
(candidate.deprecated === void 0 || Is.boolean(candidate.deprecated)) &&
|
|
(candidate.children === void 0 || Array.isArray(candidate.children));
|
|
}
|
|
DocumentSymbol.is = is;
|
|
})(DocumentSymbol || (DocumentSymbol = {}));
|
|
/**
|
|
* A set of predefined code action kinds
|
|
*/
|
|
var CodeActionKind;
|
|
(function (CodeActionKind) {
|
|
/**
|
|
* Base kind for quickfix actions: 'quickfix'
|
|
*/
|
|
CodeActionKind.QuickFix = 'quickfix';
|
|
/**
|
|
* Base kind for refactoring actions: 'refactor'
|
|
*/
|
|
CodeActionKind.Refactor = 'refactor';
|
|
/**
|
|
* Base kind for refactoring extraction actions: 'refactor.extract'
|
|
*
|
|
* Example extract actions:
|
|
*
|
|
* - Extract method
|
|
* - Extract function
|
|
* - Extract variable
|
|
* - Extract interface from class
|
|
* - ...
|
|
*/
|
|
CodeActionKind.RefactorExtract = 'refactor.extract';
|
|
/**
|
|
* Base kind for refactoring inline actions: 'refactor.inline'
|
|
*
|
|
* Example inline actions:
|
|
*
|
|
* - Inline function
|
|
* - Inline variable
|
|
* - Inline constant
|
|
* - ...
|
|
*/
|
|
CodeActionKind.RefactorInline = 'refactor.inline';
|
|
/**
|
|
* Base kind for refactoring rewrite actions: 'refactor.rewrite'
|
|
*
|
|
* Example rewrite actions:
|
|
*
|
|
* - Convert JavaScript function to class
|
|
* - Add or remove parameter
|
|
* - Encapsulate field
|
|
* - Make method static
|
|
* - Move method to base class
|
|
* - ...
|
|
*/
|
|
CodeActionKind.RefactorRewrite = 'refactor.rewrite';
|
|
/**
|
|
* Base kind for source actions: `source`
|
|
*
|
|
* Source code actions apply to the entire file.
|
|
*/
|
|
CodeActionKind.Source = 'source';
|
|
/**
|
|
* Base kind for an organize imports source action: `source.organizeImports`
|
|
*/
|
|
CodeActionKind.SourceOrganizeImports = 'source.organizeImports';
|
|
})(CodeActionKind || (CodeActionKind = {}));
|
|
/**
|
|
* The CodeActionContext namespace provides helper functions to work with
|
|
* [CodeActionContext](#CodeActionContext) literals.
|
|
*/
|
|
var CodeActionContext;
|
|
(function (CodeActionContext) {
|
|
/**
|
|
* Creates a new CodeActionContext literal.
|
|
*/
|
|
function create(diagnostics, only) {
|
|
var result = { diagnostics: diagnostics };
|
|
if (only !== void 0 && only !== null) {
|
|
result.only = only;
|
|
}
|
|
return result;
|
|
}
|
|
CodeActionContext.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [CodeActionContext](#CodeActionContext) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.defined(candidate) && Is.typedArray(candidate.diagnostics, Diagnostic.is) && (candidate.only === void 0 || Is.typedArray(candidate.only, Is.string));
|
|
}
|
|
CodeActionContext.is = is;
|
|
})(CodeActionContext || (CodeActionContext = {}));
|
|
var CodeAction;
|
|
(function (CodeAction) {
|
|
function create(title, commandOrEdit, kind) {
|
|
var result = { title: title };
|
|
if (Command.is(commandOrEdit)) {
|
|
result.command = commandOrEdit;
|
|
}
|
|
else {
|
|
result.edit = commandOrEdit;
|
|
}
|
|
if (kind !== void null) {
|
|
result.kind = kind;
|
|
}
|
|
return result;
|
|
}
|
|
CodeAction.create = create;
|
|
function is(value) {
|
|
var candidate = value;
|
|
return candidate && Is.string(candidate.title) &&
|
|
(candidate.diagnostics === void 0 || Is.typedArray(candidate.diagnostics, Diagnostic.is)) &&
|
|
(candidate.kind === void 0 || Is.string(candidate.kind)) &&
|
|
(candidate.edit !== void 0 || candidate.command !== void 0) &&
|
|
(candidate.command === void 0 || Command.is(candidate.command)) &&
|
|
(candidate.edit === void 0 || WorkspaceEdit.is(candidate.edit));
|
|
}
|
|
CodeAction.is = is;
|
|
})(CodeAction || (CodeAction = {}));
|
|
/**
|
|
* The CodeLens namespace provides helper functions to work with
|
|
* [CodeLens](#CodeLens) literals.
|
|
*/
|
|
var CodeLens;
|
|
(function (CodeLens) {
|
|
/**
|
|
* Creates a new CodeLens literal.
|
|
*/
|
|
function create(range, data) {
|
|
var result = { range: range };
|
|
if (Is.defined(data))
|
|
result.data = data;
|
|
return result;
|
|
}
|
|
CodeLens.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [CodeLens](#CodeLens) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.defined(candidate) && Range.is(candidate.range) && (Is.undefined(candidate.command) || Command.is(candidate.command));
|
|
}
|
|
CodeLens.is = is;
|
|
})(CodeLens || (CodeLens = {}));
|
|
/**
|
|
* The FormattingOptions namespace provides helper functions to work with
|
|
* [FormattingOptions](#FormattingOptions) literals.
|
|
*/
|
|
var FormattingOptions;
|
|
(function (FormattingOptions) {
|
|
/**
|
|
* Creates a new FormattingOptions literal.
|
|
*/
|
|
function create(tabSize, insertSpaces) {
|
|
return { tabSize: tabSize, insertSpaces: insertSpaces };
|
|
}
|
|
FormattingOptions.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [FormattingOptions](#FormattingOptions) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.defined(candidate) && Is.number(candidate.tabSize) && Is.boolean(candidate.insertSpaces);
|
|
}
|
|
FormattingOptions.is = is;
|
|
})(FormattingOptions || (FormattingOptions = {}));
|
|
/**
|
|
* A document link is a range in a text document that links to an internal or external resource, like another
|
|
* text document or a web site.
|
|
*/
|
|
var DocumentLink = /** @class */ (function () {
|
|
function DocumentLink() {
|
|
}
|
|
return DocumentLink;
|
|
}());
|
|
|
|
/**
|
|
* The DocumentLink namespace provides helper functions to work with
|
|
* [DocumentLink](#DocumentLink) literals.
|
|
*/
|
|
(function (DocumentLink) {
|
|
/**
|
|
* Creates a new DocumentLink literal.
|
|
*/
|
|
function create(range, target, data) {
|
|
return { range: range, target: target, data: data };
|
|
}
|
|
DocumentLink.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [DocumentLink](#DocumentLink) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.defined(candidate) && Range.is(candidate.range) && (Is.undefined(candidate.target) || Is.string(candidate.target));
|
|
}
|
|
DocumentLink.is = is;
|
|
})(DocumentLink || (DocumentLink = {}));
|
|
/**
|
|
* The SelectionRange namespace provides helper function to work with
|
|
* SelectionRange literals.
|
|
*/
|
|
var SelectionRange;
|
|
(function (SelectionRange) {
|
|
/**
|
|
* Creates a new SelectionRange
|
|
* @param range the range.
|
|
* @param parent an optional parent.
|
|
*/
|
|
function create(range, parent) {
|
|
return { range: range, parent: parent };
|
|
}
|
|
SelectionRange.create = create;
|
|
function is(value) {
|
|
var candidate = value;
|
|
return candidate !== undefined && Range.is(candidate.range) && (candidate.parent === undefined || SelectionRange.is(candidate.parent));
|
|
}
|
|
SelectionRange.is = is;
|
|
})(SelectionRange || (SelectionRange = {}));
|
|
var EOL = ['\n', '\r\n', '\r'];
|
|
var TextDocument;
|
|
(function (TextDocument) {
|
|
/**
|
|
* Creates a new ITextDocument literal from the given uri and content.
|
|
* @param uri The document's uri.
|
|
* @param languageId The document's language Id.
|
|
* @param content The document's content.
|
|
*/
|
|
function create(uri, languageId, version, content) {
|
|
return new FullTextDocument(uri, languageId, version, content);
|
|
}
|
|
TextDocument.create = create;
|
|
/**
|
|
* Checks whether the given literal conforms to the [ITextDocument](#ITextDocument) interface.
|
|
*/
|
|
function is(value) {
|
|
var candidate = value;
|
|
return Is.defined(candidate) && Is.string(candidate.uri) && (Is.undefined(candidate.languageId) || Is.string(candidate.languageId)) && Is.number(candidate.lineCount)
|
|
&& Is.func(candidate.getText) && Is.func(candidate.positionAt) && Is.func(candidate.offsetAt) ? true : false;
|
|
}
|
|
TextDocument.is = is;
|
|
function applyEdits(document, edits) {
|
|
var text = document.getText();
|
|
var sortedEdits = mergeSort(edits, function (a, b) {
|
|
var diff = a.range.start.line - b.range.start.line;
|
|
if (diff === 0) {
|
|
return a.range.start.character - b.range.start.character;
|
|
}
|
|
return diff;
|
|
});
|
|
var lastModifiedOffset = text.length;
|
|
for (var i = sortedEdits.length - 1; i >= 0; i--) {
|
|
var e = sortedEdits[i];
|
|
var startOffset = document.offsetAt(e.range.start);
|
|
var endOffset = document.offsetAt(e.range.end);
|
|
if (endOffset <= lastModifiedOffset) {
|
|
text = text.substring(0, startOffset) + e.newText + text.substring(endOffset, text.length);
|
|
}
|
|
else {
|
|
throw new Error('Overlapping edit');
|
|
}
|
|
lastModifiedOffset = startOffset;
|
|
}
|
|
return text;
|
|
}
|
|
TextDocument.applyEdits = applyEdits;
|
|
function mergeSort(data, compare) {
|
|
if (data.length <= 1) {
|
|
// sorted
|
|
return data;
|
|
}
|
|
var p = (data.length / 2) | 0;
|
|
var left = data.slice(0, p);
|
|
var right = data.slice(p);
|
|
mergeSort(left, compare);
|
|
mergeSort(right, compare);
|
|
var leftIdx = 0;
|
|
var rightIdx = 0;
|
|
var i = 0;
|
|
while (leftIdx < left.length && rightIdx < right.length) {
|
|
var ret = compare(left[leftIdx], right[rightIdx]);
|
|
if (ret <= 0) {
|
|
// smaller_equal -> take left to preserve order
|
|
data[i++] = left[leftIdx++];
|
|
}
|
|
else {
|
|
// greater -> take right
|
|
data[i++] = right[rightIdx++];
|
|
}
|
|
}
|
|
while (leftIdx < left.length) {
|
|
data[i++] = left[leftIdx++];
|
|
}
|
|
while (rightIdx < right.length) {
|
|
data[i++] = right[rightIdx++];
|
|
}
|
|
return data;
|
|
}
|
|
})(TextDocument || (TextDocument = {}));
|
|
/**
|
|
* Represents reasons why a text document is saved.
|
|
*/
|
|
var TextDocumentSaveReason;
|
|
(function (TextDocumentSaveReason) {
|
|
/**
|
|
* Manually triggered, e.g. by the user pressing save, by starting debugging,
|
|
* or by an API call.
|
|
*/
|
|
TextDocumentSaveReason.Manual = 1;
|
|
/**
|
|
* Automatic after a delay.
|
|
*/
|
|
TextDocumentSaveReason.AfterDelay = 2;
|
|
/**
|
|
* When the editor lost focus.
|
|
*/
|
|
TextDocumentSaveReason.FocusOut = 3;
|
|
})(TextDocumentSaveReason || (TextDocumentSaveReason = {}));
|
|
var FullTextDocument = /** @class */ (function () {
|
|
function FullTextDocument(uri, languageId, version, content) {
|
|
this._uri = uri;
|
|
this._languageId = languageId;
|
|
this._version = version;
|
|
this._content = content;
|
|
this._lineOffsets = null;
|
|
}
|
|
Object.defineProperty(FullTextDocument.prototype, "uri", {
|
|
get: function () {
|
|
return this._uri;
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(FullTextDocument.prototype, "languageId", {
|
|
get: function () {
|
|
return this._languageId;
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(FullTextDocument.prototype, "version", {
|
|
get: function () {
|
|
return this._version;
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
});
|
|
FullTextDocument.prototype.getText = function (range) {
|
|
if (range) {
|
|
var start = this.offsetAt(range.start);
|
|
var end = this.offsetAt(range.end);
|
|
return this._content.substring(start, end);
|
|
}
|
|
return this._content;
|
|
};
|
|
FullTextDocument.prototype.update = function (event, version) {
|
|
this._content = event.text;
|
|
this._version = version;
|
|
this._lineOffsets = null;
|
|
};
|
|
FullTextDocument.prototype.getLineOffsets = function () {
|
|
if (this._lineOffsets === null) {
|
|
var lineOffsets = [];
|
|
var text = this._content;
|
|
var isLineStart = true;
|
|
for (var i = 0; i < text.length; i++) {
|
|
if (isLineStart) {
|
|
lineOffsets.push(i);
|
|
isLineStart = false;
|
|
}
|
|
var ch = text.charAt(i);
|
|
isLineStart = (ch === '\r' || ch === '\n');
|
|
if (ch === '\r' && i + 1 < text.length && text.charAt(i + 1) === '\n') {
|
|
i++;
|
|
}
|
|
}
|
|
if (isLineStart && text.length > 0) {
|
|
lineOffsets.push(text.length);
|
|
}
|
|
this._lineOffsets = lineOffsets;
|
|
}
|
|
return this._lineOffsets;
|
|
};
|
|
FullTextDocument.prototype.positionAt = function (offset) {
|
|
offset = Math.max(Math.min(offset, this._content.length), 0);
|
|
var lineOffsets = this.getLineOffsets();
|
|
var low = 0, high = lineOffsets.length;
|
|
if (high === 0) {
|
|
return Position.create(0, offset);
|
|
}
|
|
while (low < high) {
|
|
var mid = Math.floor((low + high) / 2);
|
|
if (lineOffsets[mid] > offset) {
|
|
high = mid;
|
|
}
|
|
else {
|
|
low = mid + 1;
|
|
}
|
|
}
|
|
// low is the least x for which the line offset is larger than the current offset
|
|
// or array.length if no line offset is larger than the current offset
|
|
var line = low - 1;
|
|
return Position.create(line, offset - lineOffsets[line]);
|
|
};
|
|
FullTextDocument.prototype.offsetAt = function (position) {
|
|
var lineOffsets = this.getLineOffsets();
|
|
if (position.line >= lineOffsets.length) {
|
|
return this._content.length;
|
|
}
|
|
else if (position.line < 0) {
|
|
return 0;
|
|
}
|
|
var lineOffset = lineOffsets[position.line];
|
|
var nextLineOffset = (position.line + 1 < lineOffsets.length) ? lineOffsets[position.line + 1] : this._content.length;
|
|
return Math.max(Math.min(lineOffset + position.character, nextLineOffset), lineOffset);
|
|
};
|
|
Object.defineProperty(FullTextDocument.prototype, "lineCount", {
|
|
get: function () {
|
|
return this.getLineOffsets().length;
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
});
|
|
return FullTextDocument;
|
|
}());
|
|
var Is;
|
|
(function (Is) {
|
|
var toString = Object.prototype.toString;
|
|
function defined(value) {
|
|
return typeof value !== 'undefined';
|
|
}
|
|
Is.defined = defined;
|
|
function undefined(value) {
|
|
return typeof value === 'undefined';
|
|
}
|
|
Is.undefined = undefined;
|
|
function boolean(value) {
|
|
return value === true || value === false;
|
|
}
|
|
Is.boolean = boolean;
|
|
function string(value) {
|
|
return toString.call(value) === '[object String]';
|
|
}
|
|
Is.string = string;
|
|
function number(value) {
|
|
return toString.call(value) === '[object Number]';
|
|
}
|
|
Is.number = number;
|
|
function func(value) {
|
|
return toString.call(value) === '[object Function]';
|
|
}
|
|
Is.func = func;
|
|
function objectLiteral(value) {
|
|
// Strictly speaking class instances pass this check as well. Since the LSP
|
|
// doesn't use classes we ignore this for now. If we do we need to add something
|
|
// like this: `Object.getPrototypeOf(Object.getPrototypeOf(x)) === null`
|
|
return value !== null && typeof value === 'object';
|
|
}
|
|
Is.objectLiteral = objectLiteral;
|
|
function typedArray(value, check) {
|
|
return Array.isArray(value) && value.every(check);
|
|
}
|
|
Is.typedArray = typedArray;
|
|
})(Is || (Is = {}));
|
|
|
|
|
|
/***/ }),
|
|
/* 162 */
|
|
/***/ (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 Is = __webpack_require__(163);
|
|
const vscode_jsonrpc_1 = __webpack_require__(150);
|
|
const protocol_implementation_1 = __webpack_require__(164);
|
|
exports.ImplementationRequest = protocol_implementation_1.ImplementationRequest;
|
|
const protocol_typeDefinition_1 = __webpack_require__(165);
|
|
exports.TypeDefinitionRequest = protocol_typeDefinition_1.TypeDefinitionRequest;
|
|
const protocol_workspaceFolders_1 = __webpack_require__(166);
|
|
exports.WorkspaceFoldersRequest = protocol_workspaceFolders_1.WorkspaceFoldersRequest;
|
|
exports.DidChangeWorkspaceFoldersNotification = protocol_workspaceFolders_1.DidChangeWorkspaceFoldersNotification;
|
|
const protocol_configuration_1 = __webpack_require__(167);
|
|
exports.ConfigurationRequest = protocol_configuration_1.ConfigurationRequest;
|
|
const protocol_colorProvider_1 = __webpack_require__(168);
|
|
exports.DocumentColorRequest = protocol_colorProvider_1.DocumentColorRequest;
|
|
exports.ColorPresentationRequest = protocol_colorProvider_1.ColorPresentationRequest;
|
|
const protocol_foldingRange_1 = __webpack_require__(169);
|
|
exports.FoldingRangeRequest = protocol_foldingRange_1.FoldingRangeRequest;
|
|
const protocol_declaration_1 = __webpack_require__(170);
|
|
exports.DeclarationRequest = protocol_declaration_1.DeclarationRequest;
|
|
const protocol_selectionRange_1 = __webpack_require__(171);
|
|
exports.SelectionRangeRequest = protocol_selectionRange_1.SelectionRangeRequest;
|
|
// @ts-ignore: to avoid inlining LocatioLink as dynamic import
|
|
let __noDynamicImport;
|
|
var DocumentFilter;
|
|
(function (DocumentFilter) {
|
|
function is(value) {
|
|
let candidate = value;
|
|
return Is.string(candidate.language) || Is.string(candidate.scheme) || Is.string(candidate.pattern);
|
|
}
|
|
DocumentFilter.is = is;
|
|
})(DocumentFilter = exports.DocumentFilter || (exports.DocumentFilter = {}));
|
|
/**
|
|
* The `client/registerCapability` request is sent from the server to the client to register a new capability
|
|
* handler on the client side.
|
|
*/
|
|
var RegistrationRequest;
|
|
(function (RegistrationRequest) {
|
|
RegistrationRequest.type = new vscode_jsonrpc_1.RequestType('client/registerCapability');
|
|
})(RegistrationRequest = exports.RegistrationRequest || (exports.RegistrationRequest = {}));
|
|
/**
|
|
* The `client/unregisterCapability` request is sent from the server to the client to unregister a previously registered capability
|
|
* handler on the client side.
|
|
*/
|
|
var UnregistrationRequest;
|
|
(function (UnregistrationRequest) {
|
|
UnregistrationRequest.type = new vscode_jsonrpc_1.RequestType('client/unregisterCapability');
|
|
})(UnregistrationRequest = exports.UnregistrationRequest || (exports.UnregistrationRequest = {}));
|
|
var ResourceOperationKind;
|
|
(function (ResourceOperationKind) {
|
|
/**
|
|
* Supports creating new files and folders.
|
|
*/
|
|
ResourceOperationKind.Create = 'create';
|
|
/**
|
|
* Supports renaming existing files and folders.
|
|
*/
|
|
ResourceOperationKind.Rename = 'rename';
|
|
/**
|
|
* Supports deleting existing files and folders.
|
|
*/
|
|
ResourceOperationKind.Delete = 'delete';
|
|
})(ResourceOperationKind = exports.ResourceOperationKind || (exports.ResourceOperationKind = {}));
|
|
var FailureHandlingKind;
|
|
(function (FailureHandlingKind) {
|
|
/**
|
|
* Applying the workspace change is simply aborted if one of the changes provided
|
|
* fails. All operations executed before the failing operation stay executed.
|
|
*/
|
|
FailureHandlingKind.Abort = 'abort';
|
|
/**
|
|
* All operations are executed transactional. That means they either all
|
|
* succeed or no changes at all are applied to the workspace.
|
|
*/
|
|
FailureHandlingKind.Transactional = 'transactional';
|
|
/**
|
|
* If the workspace edit contains only textual file changes they are executed transactional.
|
|
* If resource changes (create, rename or delete file) are part of the change the failure
|
|
* handling startegy is abort.
|
|
*/
|
|
FailureHandlingKind.TextOnlyTransactional = 'textOnlyTransactional';
|
|
/**
|
|
* The client tries to undo the operations already executed. But there is no
|
|
* guaruntee that this is succeeding.
|
|
*/
|
|
FailureHandlingKind.Undo = 'undo';
|
|
})(FailureHandlingKind = exports.FailureHandlingKind || (exports.FailureHandlingKind = {}));
|
|
/**
|
|
* Defines how the host (editor) should sync
|
|
* document changes to the language server.
|
|
*/
|
|
var TextDocumentSyncKind;
|
|
(function (TextDocumentSyncKind) {
|
|
/**
|
|
* Documents should not be synced at all.
|
|
*/
|
|
TextDocumentSyncKind.None = 0;
|
|
/**
|
|
* Documents are synced by always sending the full content
|
|
* of the document.
|
|
*/
|
|
TextDocumentSyncKind.Full = 1;
|
|
/**
|
|
* Documents are synced by sending the full content on open.
|
|
* After that only incremental updates to the document are
|
|
* send.
|
|
*/
|
|
TextDocumentSyncKind.Incremental = 2;
|
|
})(TextDocumentSyncKind = exports.TextDocumentSyncKind || (exports.TextDocumentSyncKind = {}));
|
|
/**
|
|
* The initialize request is sent from the client to the server.
|
|
* It is sent once as the request after starting up the server.
|
|
* The requests parameter is of type [InitializeParams](#InitializeParams)
|
|
* the response if of type [InitializeResult](#InitializeResult) of a Thenable that
|
|
* resolves to such.
|
|
*/
|
|
var InitializeRequest;
|
|
(function (InitializeRequest) {
|
|
InitializeRequest.type = new vscode_jsonrpc_1.RequestType('initialize');
|
|
})(InitializeRequest = exports.InitializeRequest || (exports.InitializeRequest = {}));
|
|
/**
|
|
* Known error codes for an `InitializeError`;
|
|
*/
|
|
var InitializeError;
|
|
(function (InitializeError) {
|
|
/**
|
|
* If the protocol version provided by the client can't be handled by the server.
|
|
* @deprecated This initialize error got replaced by client capabilities. There is
|
|
* no version handshake in version 3.0x
|
|
*/
|
|
InitializeError.unknownProtocolVersion = 1;
|
|
})(InitializeError = exports.InitializeError || (exports.InitializeError = {}));
|
|
/**
|
|
* The intialized notification is sent from the client to the
|
|
* server after the client is fully initialized and the server
|
|
* is allowed to send requests from the server to the client.
|
|
*/
|
|
var InitializedNotification;
|
|
(function (InitializedNotification) {
|
|
InitializedNotification.type = new vscode_jsonrpc_1.NotificationType('initialized');
|
|
})(InitializedNotification = exports.InitializedNotification || (exports.InitializedNotification = {}));
|
|
//---- Shutdown Method ----
|
|
/**
|
|
* A shutdown request is sent from the client to the server.
|
|
* It is sent once when the client decides to shutdown the
|
|
* server. The only notification that is sent after a shutdown request
|
|
* is the exit event.
|
|
*/
|
|
var ShutdownRequest;
|
|
(function (ShutdownRequest) {
|
|
ShutdownRequest.type = new vscode_jsonrpc_1.RequestType0('shutdown');
|
|
})(ShutdownRequest = exports.ShutdownRequest || (exports.ShutdownRequest = {}));
|
|
//---- Exit Notification ----
|
|
/**
|
|
* The exit event is sent from the client to the server to
|
|
* ask the server to exit its process.
|
|
*/
|
|
var ExitNotification;
|
|
(function (ExitNotification) {
|
|
ExitNotification.type = new vscode_jsonrpc_1.NotificationType0('exit');
|
|
})(ExitNotification = exports.ExitNotification || (exports.ExitNotification = {}));
|
|
//---- Configuration notification ----
|
|
/**
|
|
* The configuration change notification is sent from the client to the server
|
|
* when the client's configuration has changed. The notification contains
|
|
* the changed configuration as defined by the language client.
|
|
*/
|
|
var DidChangeConfigurationNotification;
|
|
(function (DidChangeConfigurationNotification) {
|
|
DidChangeConfigurationNotification.type = new vscode_jsonrpc_1.NotificationType('workspace/didChangeConfiguration');
|
|
})(DidChangeConfigurationNotification = exports.DidChangeConfigurationNotification || (exports.DidChangeConfigurationNotification = {}));
|
|
//---- Message show and log notifications ----
|
|
/**
|
|
* The message type
|
|
*/
|
|
var MessageType;
|
|
(function (MessageType) {
|
|
/**
|
|
* An error message.
|
|
*/
|
|
MessageType.Error = 1;
|
|
/**
|
|
* A warning message.
|
|
*/
|
|
MessageType.Warning = 2;
|
|
/**
|
|
* An information message.
|
|
*/
|
|
MessageType.Info = 3;
|
|
/**
|
|
* A log message.
|
|
*/
|
|
MessageType.Log = 4;
|
|
})(MessageType = exports.MessageType || (exports.MessageType = {}));
|
|
/**
|
|
* The show message notification is sent from a server to a client to ask
|
|
* the client to display a particular message in the user interface.
|
|
*/
|
|
var ShowMessageNotification;
|
|
(function (ShowMessageNotification) {
|
|
ShowMessageNotification.type = new vscode_jsonrpc_1.NotificationType('window/showMessage');
|
|
})(ShowMessageNotification = exports.ShowMessageNotification || (exports.ShowMessageNotification = {}));
|
|
/**
|
|
* The show message request is sent from the server to the client to show a message
|
|
* and a set of options actions to the user.
|
|
*/
|
|
var ShowMessageRequest;
|
|
(function (ShowMessageRequest) {
|
|
ShowMessageRequest.type = new vscode_jsonrpc_1.RequestType('window/showMessageRequest');
|
|
})(ShowMessageRequest = exports.ShowMessageRequest || (exports.ShowMessageRequest = {}));
|
|
/**
|
|
* The log message notification is sent from the server to the client to ask
|
|
* the client to log a particular message.
|
|
*/
|
|
var LogMessageNotification;
|
|
(function (LogMessageNotification) {
|
|
LogMessageNotification.type = new vscode_jsonrpc_1.NotificationType('window/logMessage');
|
|
})(LogMessageNotification = exports.LogMessageNotification || (exports.LogMessageNotification = {}));
|
|
//---- Telemetry notification
|
|
/**
|
|
* The telemetry event notification is sent from the server to the client to ask
|
|
* the client to log telemetry data.
|
|
*/
|
|
var TelemetryEventNotification;
|
|
(function (TelemetryEventNotification) {
|
|
TelemetryEventNotification.type = new vscode_jsonrpc_1.NotificationType('telemetry/event');
|
|
})(TelemetryEventNotification = exports.TelemetryEventNotification || (exports.TelemetryEventNotification = {}));
|
|
/**
|
|
* The document open notification is sent from the client to the server to signal
|
|
* newly opened text documents. The document's truth is now managed by the client
|
|
* and the server must not try to read the document's truth using the document's
|
|
* uri. Open in this sense means it is managed by the client. It doesn't necessarily
|
|
* mean that its content is presented in an editor. An open notification must not
|
|
* be sent more than once without a corresponding close notification send before.
|
|
* This means open and close notification must be balanced and the max open count
|
|
* is one.
|
|
*/
|
|
var DidOpenTextDocumentNotification;
|
|
(function (DidOpenTextDocumentNotification) {
|
|
DidOpenTextDocumentNotification.type = new vscode_jsonrpc_1.NotificationType('textDocument/didOpen');
|
|
})(DidOpenTextDocumentNotification = exports.DidOpenTextDocumentNotification || (exports.DidOpenTextDocumentNotification = {}));
|
|
/**
|
|
* The document change notification is sent from the client to the server to signal
|
|
* changes to a text document.
|
|
*/
|
|
var DidChangeTextDocumentNotification;
|
|
(function (DidChangeTextDocumentNotification) {
|
|
DidChangeTextDocumentNotification.type = new vscode_jsonrpc_1.NotificationType('textDocument/didChange');
|
|
})(DidChangeTextDocumentNotification = exports.DidChangeTextDocumentNotification || (exports.DidChangeTextDocumentNotification = {}));
|
|
/**
|
|
* The document close notification is sent from the client to the server when
|
|
* the document got closed in the client. The document's truth now exists where
|
|
* the document's uri points to (e.g. if the document's uri is a file uri the
|
|
* truth now exists on disk). As with the open notification the close notification
|
|
* is about managing the document's content. Receiving a close notification
|
|
* doesn't mean that the document was open in an editor before. A close
|
|
* notification requires a previous open notification to be sent.
|
|
*/
|
|
var DidCloseTextDocumentNotification;
|
|
(function (DidCloseTextDocumentNotification) {
|
|
DidCloseTextDocumentNotification.type = new vscode_jsonrpc_1.NotificationType('textDocument/didClose');
|
|
})(DidCloseTextDocumentNotification = exports.DidCloseTextDocumentNotification || (exports.DidCloseTextDocumentNotification = {}));
|
|
/**
|
|
* The document save notification is sent from the client to the server when
|
|
* the document got saved in the client.
|
|
*/
|
|
var DidSaveTextDocumentNotification;
|
|
(function (DidSaveTextDocumentNotification) {
|
|
DidSaveTextDocumentNotification.type = new vscode_jsonrpc_1.NotificationType('textDocument/didSave');
|
|
})(DidSaveTextDocumentNotification = exports.DidSaveTextDocumentNotification || (exports.DidSaveTextDocumentNotification = {}));
|
|
/**
|
|
* A document will save notification is sent from the client to the server before
|
|
* the document is actually saved.
|
|
*/
|
|
var WillSaveTextDocumentNotification;
|
|
(function (WillSaveTextDocumentNotification) {
|
|
WillSaveTextDocumentNotification.type = new vscode_jsonrpc_1.NotificationType('textDocument/willSave');
|
|
})(WillSaveTextDocumentNotification = exports.WillSaveTextDocumentNotification || (exports.WillSaveTextDocumentNotification = {}));
|
|
/**
|
|
* A document will save request is sent from the client to the server before
|
|
* the document is actually saved. The request can return an array of TextEdits
|
|
* which will be applied to the text document before it is saved. Please note that
|
|
* clients might drop results if computing the text edits took too long or if a
|
|
* server constantly fails on this request. This is done to keep the save fast and
|
|
* reliable.
|
|
*/
|
|
var WillSaveTextDocumentWaitUntilRequest;
|
|
(function (WillSaveTextDocumentWaitUntilRequest) {
|
|
WillSaveTextDocumentWaitUntilRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/willSaveWaitUntil');
|
|
})(WillSaveTextDocumentWaitUntilRequest = exports.WillSaveTextDocumentWaitUntilRequest || (exports.WillSaveTextDocumentWaitUntilRequest = {}));
|
|
//---- File eventing ----
|
|
/**
|
|
* The watched files notification is sent from the client to the server when
|
|
* the client detects changes to file watched by the language client.
|
|
*/
|
|
var DidChangeWatchedFilesNotification;
|
|
(function (DidChangeWatchedFilesNotification) {
|
|
DidChangeWatchedFilesNotification.type = new vscode_jsonrpc_1.NotificationType('workspace/didChangeWatchedFiles');
|
|
})(DidChangeWatchedFilesNotification = exports.DidChangeWatchedFilesNotification || (exports.DidChangeWatchedFilesNotification = {}));
|
|
/**
|
|
* The file event type
|
|
*/
|
|
var FileChangeType;
|
|
(function (FileChangeType) {
|
|
/**
|
|
* The file got created.
|
|
*/
|
|
FileChangeType.Created = 1;
|
|
/**
|
|
* The file got changed.
|
|
*/
|
|
FileChangeType.Changed = 2;
|
|
/**
|
|
* The file got deleted.
|
|
*/
|
|
FileChangeType.Deleted = 3;
|
|
})(FileChangeType = exports.FileChangeType || (exports.FileChangeType = {}));
|
|
var WatchKind;
|
|
(function (WatchKind) {
|
|
/**
|
|
* Interested in create events.
|
|
*/
|
|
WatchKind.Create = 1;
|
|
/**
|
|
* Interested in change events
|
|
*/
|
|
WatchKind.Change = 2;
|
|
/**
|
|
* Interested in delete events
|
|
*/
|
|
WatchKind.Delete = 4;
|
|
})(WatchKind = exports.WatchKind || (exports.WatchKind = {}));
|
|
//---- Diagnostic notification ----
|
|
/**
|
|
* Diagnostics notification are sent from the server to the client to signal
|
|
* results of validation runs.
|
|
*/
|
|
var PublishDiagnosticsNotification;
|
|
(function (PublishDiagnosticsNotification) {
|
|
PublishDiagnosticsNotification.type = new vscode_jsonrpc_1.NotificationType('textDocument/publishDiagnostics');
|
|
})(PublishDiagnosticsNotification = exports.PublishDiagnosticsNotification || (exports.PublishDiagnosticsNotification = {}));
|
|
/**
|
|
* How a completion was triggered
|
|
*/
|
|
var CompletionTriggerKind;
|
|
(function (CompletionTriggerKind) {
|
|
/**
|
|
* Completion was triggered by typing an identifier (24x7 code
|
|
* complete), manual invocation (e.g Ctrl+Space) or via API.
|
|
*/
|
|
CompletionTriggerKind.Invoked = 1;
|
|
/**
|
|
* Completion was triggered by a trigger character specified by
|
|
* the `triggerCharacters` properties of the `CompletionRegistrationOptions`.
|
|
*/
|
|
CompletionTriggerKind.TriggerCharacter = 2;
|
|
/**
|
|
* Completion was re-triggered as current completion list is incomplete
|
|
*/
|
|
CompletionTriggerKind.TriggerForIncompleteCompletions = 3;
|
|
})(CompletionTriggerKind = exports.CompletionTriggerKind || (exports.CompletionTriggerKind = {}));
|
|
/**
|
|
* Request to request completion at a given text document position. The request's
|
|
* parameter is of type [TextDocumentPosition](#TextDocumentPosition) the response
|
|
* is of type [CompletionItem[]](#CompletionItem) or [CompletionList](#CompletionList)
|
|
* or a Thenable that resolves to such.
|
|
*
|
|
* The request can delay the computation of the [`detail`](#CompletionItem.detail)
|
|
* and [`documentation`](#CompletionItem.documentation) properties to the `completionItem/resolve`
|
|
* request. However, properties that are needed for the initial sorting and filtering, like `sortText`,
|
|
* `filterText`, `insertText`, and `textEdit`, must not be changed during resolve.
|
|
*/
|
|
var CompletionRequest;
|
|
(function (CompletionRequest) {
|
|
CompletionRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/completion');
|
|
})(CompletionRequest = exports.CompletionRequest || (exports.CompletionRequest = {}));
|
|
/**
|
|
* Request to resolve additional information for a given completion item.The request's
|
|
* parameter is of type [CompletionItem](#CompletionItem) the response
|
|
* is of type [CompletionItem](#CompletionItem) or a Thenable that resolves to such.
|
|
*/
|
|
var CompletionResolveRequest;
|
|
(function (CompletionResolveRequest) {
|
|
CompletionResolveRequest.type = new vscode_jsonrpc_1.RequestType('completionItem/resolve');
|
|
})(CompletionResolveRequest = exports.CompletionResolveRequest || (exports.CompletionResolveRequest = {}));
|
|
//---- Hover Support -------------------------------
|
|
/**
|
|
* Request to request hover information at a given text document position. The request's
|
|
* parameter is of type [TextDocumentPosition](#TextDocumentPosition) the response is of
|
|
* type [Hover](#Hover) or a Thenable that resolves to such.
|
|
*/
|
|
var HoverRequest;
|
|
(function (HoverRequest) {
|
|
HoverRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/hover');
|
|
})(HoverRequest = exports.HoverRequest || (exports.HoverRequest = {}));
|
|
var SignatureHelpRequest;
|
|
(function (SignatureHelpRequest) {
|
|
SignatureHelpRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/signatureHelp');
|
|
})(SignatureHelpRequest = exports.SignatureHelpRequest || (exports.SignatureHelpRequest = {}));
|
|
//---- Goto Definition -------------------------------------
|
|
/**
|
|
* A request to resolve the definition location of a symbol at a given text
|
|
* document position. The request's parameter is of type [TextDocumentPosition]
|
|
* (#TextDocumentPosition) the response is of either type [Definition](#Definition)
|
|
* or a typed array of [DefinitionLink](#DefinitionLink) or a Thenable that resolves
|
|
* to such.
|
|
*/
|
|
var DefinitionRequest;
|
|
(function (DefinitionRequest) {
|
|
DefinitionRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/definition');
|
|
})(DefinitionRequest = exports.DefinitionRequest || (exports.DefinitionRequest = {}));
|
|
/**
|
|
* A request to resolve project-wide references for the symbol denoted
|
|
* by the given text document position. The request's parameter is of
|
|
* type [ReferenceParams](#ReferenceParams) the response is of type
|
|
* [Location[]](#Location) or a Thenable that resolves to such.
|
|
*/
|
|
var ReferencesRequest;
|
|
(function (ReferencesRequest) {
|
|
ReferencesRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/references');
|
|
})(ReferencesRequest = exports.ReferencesRequest || (exports.ReferencesRequest = {}));
|
|
//---- Document Highlight ----------------------------------
|
|
/**
|
|
* Request to resolve a [DocumentHighlight](#DocumentHighlight) for a given
|
|
* text document position. The request's parameter is of type [TextDocumentPosition]
|
|
* (#TextDocumentPosition) the request response is of type [DocumentHighlight[]]
|
|
* (#DocumentHighlight) or a Thenable that resolves to such.
|
|
*/
|
|
var DocumentHighlightRequest;
|
|
(function (DocumentHighlightRequest) {
|
|
DocumentHighlightRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/documentHighlight');
|
|
})(DocumentHighlightRequest = exports.DocumentHighlightRequest || (exports.DocumentHighlightRequest = {}));
|
|
//---- Document Symbol Provider ---------------------------
|
|
/**
|
|
* A request to list all symbols found in a given text document. The request's
|
|
* parameter is of type [TextDocumentIdentifier](#TextDocumentIdentifier) the
|
|
* response is of type [SymbolInformation[]](#SymbolInformation) or a Thenable
|
|
* that resolves to such.
|
|
*/
|
|
var DocumentSymbolRequest;
|
|
(function (DocumentSymbolRequest) {
|
|
DocumentSymbolRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/documentSymbol');
|
|
})(DocumentSymbolRequest = exports.DocumentSymbolRequest || (exports.DocumentSymbolRequest = {}));
|
|
//---- Workspace Symbol Provider ---------------------------
|
|
/**
|
|
* A request to list project-wide symbols matching the query string given
|
|
* by the [WorkspaceSymbolParams](#WorkspaceSymbolParams). The response is
|
|
* of type [SymbolInformation[]](#SymbolInformation) or a Thenable that
|
|
* resolves to such.
|
|
*/
|
|
var WorkspaceSymbolRequest;
|
|
(function (WorkspaceSymbolRequest) {
|
|
WorkspaceSymbolRequest.type = new vscode_jsonrpc_1.RequestType('workspace/symbol');
|
|
})(WorkspaceSymbolRequest = exports.WorkspaceSymbolRequest || (exports.WorkspaceSymbolRequest = {}));
|
|
/**
|
|
* A request to provide commands for the given text document and range.
|
|
*/
|
|
var CodeActionRequest;
|
|
(function (CodeActionRequest) {
|
|
CodeActionRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/codeAction');
|
|
})(CodeActionRequest = exports.CodeActionRequest || (exports.CodeActionRequest = {}));
|
|
/**
|
|
* A request to provide code lens for the given text document.
|
|
*/
|
|
var CodeLensRequest;
|
|
(function (CodeLensRequest) {
|
|
CodeLensRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/codeLens');
|
|
})(CodeLensRequest = exports.CodeLensRequest || (exports.CodeLensRequest = {}));
|
|
/**
|
|
* A request to resolve a command for a given code lens.
|
|
*/
|
|
var CodeLensResolveRequest;
|
|
(function (CodeLensResolveRequest) {
|
|
CodeLensResolveRequest.type = new vscode_jsonrpc_1.RequestType('codeLens/resolve');
|
|
})(CodeLensResolveRequest = exports.CodeLensResolveRequest || (exports.CodeLensResolveRequest = {}));
|
|
/**
|
|
* A request to to format a whole document.
|
|
*/
|
|
var DocumentFormattingRequest;
|
|
(function (DocumentFormattingRequest) {
|
|
DocumentFormattingRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/formatting');
|
|
})(DocumentFormattingRequest = exports.DocumentFormattingRequest || (exports.DocumentFormattingRequest = {}));
|
|
/**
|
|
* A request to to format a range in a document.
|
|
*/
|
|
var DocumentRangeFormattingRequest;
|
|
(function (DocumentRangeFormattingRequest) {
|
|
DocumentRangeFormattingRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/rangeFormatting');
|
|
})(DocumentRangeFormattingRequest = exports.DocumentRangeFormattingRequest || (exports.DocumentRangeFormattingRequest = {}));
|
|
/**
|
|
* A request to format a document on type.
|
|
*/
|
|
var DocumentOnTypeFormattingRequest;
|
|
(function (DocumentOnTypeFormattingRequest) {
|
|
DocumentOnTypeFormattingRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/onTypeFormatting');
|
|
})(DocumentOnTypeFormattingRequest = exports.DocumentOnTypeFormattingRequest || (exports.DocumentOnTypeFormattingRequest = {}));
|
|
/**
|
|
* A request to rename a symbol.
|
|
*/
|
|
var RenameRequest;
|
|
(function (RenameRequest) {
|
|
RenameRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/rename');
|
|
})(RenameRequest = exports.RenameRequest || (exports.RenameRequest = {}));
|
|
/**
|
|
* A request to test and perform the setup necessary for a rename.
|
|
*/
|
|
var PrepareRenameRequest;
|
|
(function (PrepareRenameRequest) {
|
|
PrepareRenameRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/prepareRename');
|
|
})(PrepareRenameRequest = exports.PrepareRenameRequest || (exports.PrepareRenameRequest = {}));
|
|
/**
|
|
* A request to provide document links
|
|
*/
|
|
var DocumentLinkRequest;
|
|
(function (DocumentLinkRequest) {
|
|
DocumentLinkRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/documentLink');
|
|
})(DocumentLinkRequest = exports.DocumentLinkRequest || (exports.DocumentLinkRequest = {}));
|
|
/**
|
|
* Request to resolve additional information for a given document link. The request's
|
|
* parameter is of type [DocumentLink](#DocumentLink) the response
|
|
* is of type [DocumentLink](#DocumentLink) or a Thenable that resolves to such.
|
|
*/
|
|
var DocumentLinkResolveRequest;
|
|
(function (DocumentLinkResolveRequest) {
|
|
DocumentLinkResolveRequest.type = new vscode_jsonrpc_1.RequestType('documentLink/resolve');
|
|
})(DocumentLinkResolveRequest = exports.DocumentLinkResolveRequest || (exports.DocumentLinkResolveRequest = {}));
|
|
/**
|
|
* A request send from the client to the server to execute a command. The request might return
|
|
* a workspace edit which the client will apply to the workspace.
|
|
*/
|
|
var ExecuteCommandRequest;
|
|
(function (ExecuteCommandRequest) {
|
|
ExecuteCommandRequest.type = new vscode_jsonrpc_1.RequestType('workspace/executeCommand');
|
|
})(ExecuteCommandRequest = exports.ExecuteCommandRequest || (exports.ExecuteCommandRequest = {}));
|
|
/**
|
|
* A request sent from the server to the client to modified certain resources.
|
|
*/
|
|
var ApplyWorkspaceEditRequest;
|
|
(function (ApplyWorkspaceEditRequest) {
|
|
ApplyWorkspaceEditRequest.type = new vscode_jsonrpc_1.RequestType('workspace/applyEdit');
|
|
})(ApplyWorkspaceEditRequest = exports.ApplyWorkspaceEditRequest || (exports.ApplyWorkspaceEditRequest = {}));
|
|
|
|
|
|
/***/ }),
|
|
/* 163 */
|
|
/***/ (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 });
|
|
function boolean(value) {
|
|
return value === true || value === false;
|
|
}
|
|
exports.boolean = boolean;
|
|
function string(value) {
|
|
return typeof value === 'string' || value instanceof String;
|
|
}
|
|
exports.string = string;
|
|
function number(value) {
|
|
return typeof value === 'number' || value instanceof Number;
|
|
}
|
|
exports.number = number;
|
|
function error(value) {
|
|
return value instanceof Error;
|
|
}
|
|
exports.error = error;
|
|
function func(value) {
|
|
return typeof value === 'function';
|
|
}
|
|
exports.func = func;
|
|
function array(value) {
|
|
return Array.isArray(value);
|
|
}
|
|
exports.array = array;
|
|
function stringArray(value) {
|
|
return array(value) && value.every(elem => string(elem));
|
|
}
|
|
exports.stringArray = stringArray;
|
|
function typedArray(value, check) {
|
|
return Array.isArray(value) && value.every(check);
|
|
}
|
|
exports.typedArray = typedArray;
|
|
function thenable(value) {
|
|
return value && func(value.then);
|
|
}
|
|
exports.thenable = thenable;
|
|
|
|
|
|
/***/ }),
|
|
/* 164 */
|
|
/***/ (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_jsonrpc_1 = __webpack_require__(150);
|
|
// @ts-ignore: to avoid inlining LocatioLink as dynamic import
|
|
let __noDynamicImport;
|
|
/**
|
|
* A request to resolve the implementation locations of a symbol at a given text
|
|
* document position. The request's parameter is of type [TextDocumentPositioParams]
|
|
* (#TextDocumentPositionParams) the response is of type [Definition](#Definition) or a
|
|
* Thenable that resolves to such.
|
|
*/
|
|
var ImplementationRequest;
|
|
(function (ImplementationRequest) {
|
|
ImplementationRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/implementation');
|
|
})(ImplementationRequest = exports.ImplementationRequest || (exports.ImplementationRequest = {}));
|
|
|
|
|
|
/***/ }),
|
|
/* 165 */
|
|
/***/ (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_jsonrpc_1 = __webpack_require__(150);
|
|
// @ts-ignore: to avoid inlining LocatioLink as dynamic import
|
|
let __noDynamicImport;
|
|
/**
|
|
* A request to resolve the type definition locations of a symbol at a given text
|
|
* document position. The request's parameter is of type [TextDocumentPositioParams]
|
|
* (#TextDocumentPositionParams) the response is of type [Definition](#Definition) or a
|
|
* Thenable that resolves to such.
|
|
*/
|
|
var TypeDefinitionRequest;
|
|
(function (TypeDefinitionRequest) {
|
|
TypeDefinitionRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/typeDefinition');
|
|
})(TypeDefinitionRequest = exports.TypeDefinitionRequest || (exports.TypeDefinitionRequest = {}));
|
|
|
|
|
|
/***/ }),
|
|
/* 166 */
|
|
/***/ (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_jsonrpc_1 = __webpack_require__(150);
|
|
/**
|
|
* The `workspace/workspaceFolders` is sent from the server to the client to fetch the open workspace folders.
|
|
*/
|
|
var WorkspaceFoldersRequest;
|
|
(function (WorkspaceFoldersRequest) {
|
|
WorkspaceFoldersRequest.type = new vscode_jsonrpc_1.RequestType0('workspace/workspaceFolders');
|
|
})(WorkspaceFoldersRequest = exports.WorkspaceFoldersRequest || (exports.WorkspaceFoldersRequest = {}));
|
|
/**
|
|
* The `workspace/didChangeWorkspaceFolders` notification is sent from the client to the server when the workspace
|
|
* folder configuration changes.
|
|
*/
|
|
var DidChangeWorkspaceFoldersNotification;
|
|
(function (DidChangeWorkspaceFoldersNotification) {
|
|
DidChangeWorkspaceFoldersNotification.type = new vscode_jsonrpc_1.NotificationType('workspace/didChangeWorkspaceFolders');
|
|
})(DidChangeWorkspaceFoldersNotification = exports.DidChangeWorkspaceFoldersNotification || (exports.DidChangeWorkspaceFoldersNotification = {}));
|
|
|
|
|
|
/***/ }),
|
|
/* 167 */
|
|
/***/ (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_jsonrpc_1 = __webpack_require__(150);
|
|
/**
|
|
* The 'workspace/configuration' request is sent from the server to the client to fetch a certain
|
|
* configuration setting.
|
|
*
|
|
* This pull model replaces the old push model were the client signaled configuration change via an
|
|
* event. If the server still needs to react to configuration changes (since the server caches the
|
|
* result of `workspace/configuration` requests) the server should register for an empty configuration
|
|
* change event and empty the cache if such an event is received.
|
|
*/
|
|
var ConfigurationRequest;
|
|
(function (ConfigurationRequest) {
|
|
ConfigurationRequest.type = new vscode_jsonrpc_1.RequestType('workspace/configuration');
|
|
})(ConfigurationRequest = exports.ConfigurationRequest || (exports.ConfigurationRequest = {}));
|
|
|
|
|
|
/***/ }),
|
|
/* 168 */
|
|
/***/ (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_jsonrpc_1 = __webpack_require__(150);
|
|
/**
|
|
* A request to list all color symbols found in a given text document. The request's
|
|
* parameter is of type [DocumentColorParams](#DocumentColorParams) the
|
|
* response is of type [ColorInformation[]](#ColorInformation) or a Thenable
|
|
* that resolves to such.
|
|
*/
|
|
var DocumentColorRequest;
|
|
(function (DocumentColorRequest) {
|
|
DocumentColorRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/documentColor');
|
|
})(DocumentColorRequest = exports.DocumentColorRequest || (exports.DocumentColorRequest = {}));
|
|
/**
|
|
* A request to list all presentation for a color. The request's
|
|
* parameter is of type [ColorPresentationParams](#ColorPresentationParams) the
|
|
* response is of type [ColorInformation[]](#ColorInformation) or a Thenable
|
|
* that resolves to such.
|
|
*/
|
|
var ColorPresentationRequest;
|
|
(function (ColorPresentationRequest) {
|
|
ColorPresentationRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/colorPresentation');
|
|
})(ColorPresentationRequest = exports.ColorPresentationRequest || (exports.ColorPresentationRequest = {}));
|
|
|
|
|
|
/***/ }),
|
|
/* 169 */
|
|
/***/ (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_jsonrpc_1 = __webpack_require__(150);
|
|
/**
|
|
* Enum of known range kinds
|
|
*/
|
|
var FoldingRangeKind;
|
|
(function (FoldingRangeKind) {
|
|
/**
|
|
* Folding range for a comment
|
|
*/
|
|
FoldingRangeKind["Comment"] = "comment";
|
|
/**
|
|
* Folding range for a imports or includes
|
|
*/
|
|
FoldingRangeKind["Imports"] = "imports";
|
|
/**
|
|
* Folding range for a region (e.g. `#region`)
|
|
*/
|
|
FoldingRangeKind["Region"] = "region";
|
|
})(FoldingRangeKind = exports.FoldingRangeKind || (exports.FoldingRangeKind = {}));
|
|
/**
|
|
* A request to provide folding ranges in a document. The request's
|
|
* parameter is of type [FoldingRangeParams](#FoldingRangeParams), the
|
|
* response is of type [FoldingRangeList](#FoldingRangeList) or a Thenable
|
|
* that resolves to such.
|
|
*/
|
|
var FoldingRangeRequest;
|
|
(function (FoldingRangeRequest) {
|
|
FoldingRangeRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/foldingRange');
|
|
})(FoldingRangeRequest = exports.FoldingRangeRequest || (exports.FoldingRangeRequest = {}));
|
|
|
|
|
|
/***/ }),
|
|
/* 170 */
|
|
/***/ (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_jsonrpc_1 = __webpack_require__(150);
|
|
// @ts-ignore: to avoid inlining LocatioLink as dynamic import
|
|
let __noDynamicImport;
|
|
/**
|
|
* A request to resolve the type definition locations of a symbol at a given text
|
|
* document position. The request's parameter is of type [TextDocumentPositioParams]
|
|
* (#TextDocumentPositionParams) the response is of type [Declaration](#Declaration)
|
|
* or a typed array of [DeclarationLink](#DeclarationLink) or a Thenable that resolves
|
|
* to such.
|
|
*/
|
|
var DeclarationRequest;
|
|
(function (DeclarationRequest) {
|
|
DeclarationRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/declaration');
|
|
})(DeclarationRequest = exports.DeclarationRequest || (exports.DeclarationRequest = {}));
|
|
|
|
|
|
/***/ }),
|
|
/* 171 */
|
|
/***/ (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_jsonrpc_1 = __webpack_require__(150);
|
|
/**
|
|
* A request to provide selection ranges in a document. The request's
|
|
* parameter is of type [SelectionRangeParams](#SelectionRangeParams), the
|
|
* response is of type [SelectionRange[]](#SelectionRange[]) or a Thenable
|
|
* that resolves to such.
|
|
*/
|
|
var SelectionRangeRequest;
|
|
(function (SelectionRangeRequest) {
|
|
SelectionRangeRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/selectionRange');
|
|
})(SelectionRangeRequest = exports.SelectionRangeRequest || (exports.SelectionRangeRequest = {}));
|
|
|
|
|
|
/***/ }),
|
|
/* 172 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
/* --------------------------------------------------------------------------------------------
|
|
* Copyright (c) TypeFox and others. 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_jsonrpc_1 = __webpack_require__(150);
|
|
/**
|
|
* The direction of a call hierarchy request.
|
|
*/
|
|
var CallHierarchyDirection;
|
|
(function (CallHierarchyDirection) {
|
|
/**
|
|
* The callers
|
|
*/
|
|
CallHierarchyDirection.CallsFrom = 1;
|
|
/**
|
|
* The callees
|
|
*/
|
|
CallHierarchyDirection.CallsTo = 2;
|
|
})(CallHierarchyDirection = exports.CallHierarchyDirection || (exports.CallHierarchyDirection = {}));
|
|
/**
|
|
* Request to provide the call hierarchy at a given text document position.
|
|
*
|
|
* The request's parameter is of type [CallHierarchyParams](#CallHierarchyParams). The response
|
|
* is of type [CallHierarchyCall[]](#CallHierarchyCall) or a Thenable that resolves to such.
|
|
*
|
|
* Evaluates the symbol defined (or referenced) at the given position, and returns all incoming or outgoing calls to the symbol(s).
|
|
*/
|
|
var CallHierarchyRequest;
|
|
(function (CallHierarchyRequest) {
|
|
CallHierarchyRequest.type = new vscode_jsonrpc_1.RequestType('textDocument/callHierarchy');
|
|
})(CallHierarchyRequest = exports.CallHierarchyRequest || (exports.CallHierarchyRequest = {}));
|
|
|
|
|
|
/***/ }),
|
|
/* 173 */
|
|
/***/ (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_jsonrpc_1 = __webpack_require__(150);
|
|
/**
|
|
* The `window/progress/start` notification is sent from the server to the client
|
|
* to initiate a progress.
|
|
*/
|
|
var ProgressStartNotification;
|
|
(function (ProgressStartNotification) {
|
|
ProgressStartNotification.type = new vscode_jsonrpc_1.NotificationType('window/progress/start');
|
|
})(ProgressStartNotification = exports.ProgressStartNotification || (exports.ProgressStartNotification = {}));
|
|
/**
|
|
* The `window/progress/report` notification is sent from the server to the client
|
|
* to initiate a progress.
|
|
*/
|
|
var ProgressReportNotification;
|
|
(function (ProgressReportNotification) {
|
|
ProgressReportNotification.type = new vscode_jsonrpc_1.NotificationType('window/progress/report');
|
|
})(ProgressReportNotification = exports.ProgressReportNotification || (exports.ProgressReportNotification = {}));
|
|
/**
|
|
* The `window/progress/done` notification is sent from the server to the client
|
|
* to initiate a progress.
|
|
*/
|
|
var ProgressDoneNotification;
|
|
(function (ProgressDoneNotification) {
|
|
ProgressDoneNotification.type = new vscode_jsonrpc_1.NotificationType('window/progress/done');
|
|
})(ProgressDoneNotification = exports.ProgressDoneNotification || (exports.ProgressDoneNotification = {}));
|
|
/**
|
|
* The `window/progress/cancel` notification is sent client to the server to cancel a progress
|
|
* initiated on the server side.
|
|
*/
|
|
var ProgressCancelNotification;
|
|
(function (ProgressCancelNotification) {
|
|
ProgressCancelNotification.type = new vscode_jsonrpc_1.NotificationType('window/progress/cancel');
|
|
})(ProgressCancelNotification = exports.ProgressCancelNotification || (exports.ProgressCancelNotification = {}));
|
|
|
|
|
|
/***/ }),
|
|
/* 174 */
|
|
/***/ (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__(175);
|
|
const debounce_1 = tslib_1.__importDefault(__webpack_require__(176));
|
|
const fs_1 = tslib_1.__importDefault(__webpack_require__(55));
|
|
const isuri_1 = tslib_1.__importDefault(__webpack_require__(177));
|
|
const mkdirp_1 = tslib_1.__importDefault(__webpack_require__(179));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const which_1 = tslib_1.__importDefault(__webpack_require__(181));
|
|
const platform = tslib_1.__importStar(__webpack_require__(185));
|
|
exports.platform = platform;
|
|
const logger = __webpack_require__(186)('util-index');
|
|
const prefix = '[coc.nvim] ';
|
|
function escapeSingleQuote(str) {
|
|
return str.replace(/'/g, "''");
|
|
}
|
|
exports.escapeSingleQuote = escapeSingleQuote;
|
|
function echoErr(nvim, msg) {
|
|
echoMsg(nvim, prefix + msg, 'Error'); // tslint:disable-line
|
|
}
|
|
exports.echoErr = echoErr;
|
|
function echoWarning(nvim, msg) {
|
|
echoMsg(nvim, prefix + msg, 'WarningMsg'); // tslint:disable-line
|
|
}
|
|
exports.echoWarning = echoWarning;
|
|
function echoMessage(nvim, msg) {
|
|
echoMsg(nvim, prefix + msg, 'MoreMsg'); // tslint:disable-line
|
|
}
|
|
exports.echoMessage = echoMessage;
|
|
function wait(ms) {
|
|
return new Promise(resolve => {
|
|
setTimeout(() => {
|
|
resolve();
|
|
}, ms);
|
|
});
|
|
}
|
|
exports.wait = wait;
|
|
function echoMsg(nvim, msg, hl) {
|
|
let method = process.env.VIM_NODE_RPC == '1' ? 'callTimer' : 'call';
|
|
nvim[method]('coc#util#echo_messages', [hl, msg.split('\n')], true);
|
|
}
|
|
function getUri(fullpath, id, buftype, isCygwin) {
|
|
if (!fullpath)
|
|
return `untitled:${id}`;
|
|
if (platform.isWindows && !isCygwin)
|
|
fullpath = path_1.default.win32.normalize(fullpath);
|
|
if (path_1.default.isAbsolute(fullpath))
|
|
return vscode_uri_1.URI.file(fullpath).toString();
|
|
if (isuri_1.default.isValid(fullpath))
|
|
return vscode_uri_1.URI.parse(fullpath).toString();
|
|
if (buftype != '')
|
|
return `${buftype}:${id}`;
|
|
return `unknown:${id}`;
|
|
}
|
|
exports.getUri = getUri;
|
|
function disposeAll(disposables) {
|
|
while (disposables.length) {
|
|
const item = disposables.pop();
|
|
if (item) {
|
|
item.dispose();
|
|
}
|
|
}
|
|
}
|
|
exports.disposeAll = disposeAll;
|
|
function executable(command) {
|
|
try {
|
|
which_1.default.sync(command);
|
|
}
|
|
catch (e) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
exports.executable = executable;
|
|
function runCommand(cmd, opts = {}, timeout) {
|
|
if (!platform.isWindows) {
|
|
opts.shell = opts.shell || process.env.SHELL;
|
|
}
|
|
return new Promise((resolve, reject) => {
|
|
let timer;
|
|
if (timeout) {
|
|
timer = setTimeout(() => {
|
|
reject(new Error(`timeout after ${timeout}s`));
|
|
}, timeout * 1000);
|
|
}
|
|
child_process_1.exec(cmd, opts, (err, stdout, stderr) => {
|
|
if (timer)
|
|
clearTimeout(timer);
|
|
if (err) {
|
|
reject(new Error(`exited with ${err.code}\n${err}\n${stderr}`));
|
|
return;
|
|
}
|
|
resolve(stdout);
|
|
});
|
|
});
|
|
}
|
|
exports.runCommand = runCommand;
|
|
function watchFile(filepath, onChange) {
|
|
let callback = debounce_1.default(onChange, 100);
|
|
try {
|
|
let watcher = fs_1.default.watch(filepath, {
|
|
persistent: true,
|
|
recursive: false,
|
|
encoding: 'utf8'
|
|
}, () => {
|
|
callback();
|
|
});
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
watcher.close();
|
|
});
|
|
}
|
|
catch (e) {
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
// noop
|
|
});
|
|
}
|
|
}
|
|
exports.watchFile = watchFile;
|
|
function isRunning(pid) {
|
|
try {
|
|
let res = process.kill(pid, 0);
|
|
return res == true;
|
|
}
|
|
catch (e) {
|
|
return e.code === 'EPERM';
|
|
}
|
|
}
|
|
exports.isRunning = isRunning;
|
|
function getKeymapModifier(mode) {
|
|
if (mode == 'o' || mode == 'x' || mode == 'v')
|
|
return '<C-U>';
|
|
if (mode == 'n')
|
|
return '';
|
|
if (mode == 'i')
|
|
return '<C-o>';
|
|
if (mode == 's')
|
|
return '<Esc>';
|
|
return '';
|
|
}
|
|
exports.getKeymapModifier = getKeymapModifier;
|
|
async function mkdirp(path, mode) {
|
|
return new Promise(resolve => {
|
|
mkdirp_1.default(path, { mode }, err => {
|
|
if (err)
|
|
return resolve(false);
|
|
resolve(true);
|
|
});
|
|
});
|
|
}
|
|
exports.mkdirp = mkdirp;
|
|
// consider textDocument without version to be valid
|
|
function isDocumentEdit(edit) {
|
|
if (edit == null)
|
|
return false;
|
|
if (!vscode_languageserver_protocol_1.TextDocumentIdentifier.is(edit.textDocument))
|
|
return false;
|
|
if (!Array.isArray(edit.edits))
|
|
return false;
|
|
return true;
|
|
}
|
|
exports.isDocumentEdit = isDocumentEdit;
|
|
function concurrent(fns, limit = Infinity) {
|
|
if (fns.length == 0)
|
|
return Promise.resolve([]);
|
|
return new Promise((resolve, rejrect) => {
|
|
let remain = fns.slice();
|
|
let results = [];
|
|
let next = () => {
|
|
if (remain.length == 0) {
|
|
return resolve(results);
|
|
}
|
|
let list = remain.splice(0, limit);
|
|
Promise.all(list.map(fn => fn())).then(res => {
|
|
results.push(...res);
|
|
next();
|
|
}, rejrect);
|
|
};
|
|
next();
|
|
});
|
|
}
|
|
exports.concurrent = concurrent;
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
/* 175 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("child_process");
|
|
|
|
/***/ }),
|
|
/* 176 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* Returns a function, that, as long as it continues to be invoked, will not
|
|
* be triggered. The function will be called after it stops being called for
|
|
* N milliseconds. If `immediate` is passed, trigger the function on the
|
|
* leading edge, instead of the trailing. The function also has a property 'clear'
|
|
* that is a function which will clear the timer to prevent previously scheduled executions.
|
|
*
|
|
* @source underscore.js
|
|
* @see http://unscriptable.com/2009/03/20/debouncing-javascript-methods/
|
|
* @param {Function} function to wrap
|
|
* @param {Number} timeout in ms (`100`)
|
|
* @param {Boolean} whether to execute at the beginning (`false`)
|
|
* @api public
|
|
*/
|
|
function debounce(func, wait, immediate){
|
|
var timeout, args, context, timestamp, result;
|
|
if (null == wait) wait = 100;
|
|
|
|
function later() {
|
|
var last = Date.now() - timestamp;
|
|
|
|
if (last < wait && last >= 0) {
|
|
timeout = setTimeout(later, wait - last);
|
|
} else {
|
|
timeout = null;
|
|
if (!immediate) {
|
|
result = func.apply(context, args);
|
|
context = args = null;
|
|
}
|
|
}
|
|
};
|
|
|
|
var debounced = function(){
|
|
context = this;
|
|
args = arguments;
|
|
timestamp = Date.now();
|
|
var callNow = immediate && !timeout;
|
|
if (!timeout) timeout = setTimeout(later, wait);
|
|
if (callNow) {
|
|
result = func.apply(context, args);
|
|
context = args = null;
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
debounced.clear = function() {
|
|
if (timeout) {
|
|
clearTimeout(timeout);
|
|
timeout = null;
|
|
}
|
|
};
|
|
|
|
debounced.flush = function() {
|
|
if (timeout) {
|
|
result = func.apply(context, args);
|
|
context = args = null;
|
|
|
|
clearTimeout(timeout);
|
|
timeout = null;
|
|
}
|
|
};
|
|
|
|
return debounced;
|
|
};
|
|
|
|
// Adds compatibility for ES modules
|
|
debounce.debounce = debounce;
|
|
|
|
module.exports = debounce;
|
|
|
|
|
|
/***/ }),
|
|
/* 177 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var rfc3986 = __webpack_require__(178);
|
|
|
|
// See: https://github.com/hapijs/hoek/blob/f62961d3d07aca68ab11480893e6e80a421914b4/lib/index.js#L783-L787
|
|
function escapeRegex(string) {
|
|
// Escape ^$.*+-?=!:|\/()[]{},
|
|
return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&');
|
|
}
|
|
|
|
var internals = {
|
|
Uri: {
|
|
createUriRegex: function (options) {
|
|
options = options || {};
|
|
|
|
if (typeof options !== 'object' || Array.isArray(options)) {
|
|
throw new Error('options must be an object');
|
|
}
|
|
|
|
var customScheme = '';
|
|
|
|
// If we were passed a scheme, use it instead of the generic one
|
|
if (options.scheme) {
|
|
if (!Array.isArray(options.scheme)) {
|
|
options.scheme = [options.scheme];
|
|
}
|
|
|
|
if (options.scheme.length <= 0) {
|
|
throw new Error('scheme must have at least 1 scheme specified');
|
|
}
|
|
|
|
for (var i = 0; i < options.scheme.length; ++i) {
|
|
var currentScheme = options.scheme[i];
|
|
|
|
if (!(currentScheme instanceof RegExp || typeof currentScheme === 'string')) {
|
|
throw new Error('scheme must only contain Regular Expressions or Strings');
|
|
}
|
|
|
|
// Add OR separators if a value already exists
|
|
customScheme = customScheme + (customScheme ? '|' : '');
|
|
|
|
// If someone wants to match HTTP or HTTPS for example then we need to support both RegExp and String so we don't escape their pattern unknowingly.
|
|
if (currentScheme instanceof RegExp) {
|
|
customScheme = customScheme + currentScheme.source;
|
|
} else {
|
|
if (!/[a-zA-Z][a-zA-Z0-9+-\.]*/.test(currentScheme)) {
|
|
throw new Error('scheme at position ' + i + ' must be a valid scheme');
|
|
}
|
|
customScheme = customScheme + escapeRegex(currentScheme);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// Have to put this in a non-capturing group to handle the OR statements
|
|
var scheme = '(?:' + (customScheme || rfc3986.scheme) + ')';
|
|
|
|
/**
|
|
* URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
|
|
*
|
|
* OR
|
|
*
|
|
* relative-ref = relative-part [ "?" query ] [ "#" fragment ]
|
|
*/
|
|
return new RegExp('^(?:' + scheme + ':' + rfc3986.hierPart + ')(?:\\?' + rfc3986.query + ')?(?:#' + rfc3986.fragment + ')?$');
|
|
},
|
|
uriRegex: new RegExp(rfc3986.uri)
|
|
}
|
|
};
|
|
|
|
internals.Uri.isValid = function (val) {
|
|
return internals.Uri.uriRegex.test(val);
|
|
};
|
|
|
|
module.exports = {
|
|
createUriRegex: internals.Uri.createUriRegex,
|
|
|
|
uriRegex: internals.Uri.uriRegex,
|
|
isValid: internals.Uri.isValid
|
|
};
|
|
|
|
/***/ }),
|
|
/* 178 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
// Load modules
|
|
|
|
// Delcare internals
|
|
|
|
var internals = {
|
|
rfc3986: {}
|
|
};
|
|
|
|
internals.generate = function () {
|
|
|
|
/**
|
|
* elements separated by forward slash ("/") are alternatives.
|
|
*/
|
|
var or = '|';
|
|
|
|
/**
|
|
* DIGIT = %x30-39 ; 0-9
|
|
*/
|
|
var digit = '0-9';
|
|
var digitOnly = '[' + digit + ']';
|
|
|
|
/**
|
|
* ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
|
|
*/
|
|
var alpha = 'a-zA-Z';
|
|
var alphaOnly = '[' + alpha + ']';
|
|
|
|
/**
|
|
* cidr = DIGIT ; 0-9
|
|
* / %x31-32 DIGIT ; 10-29
|
|
* / "3" %x30-32 ; 30-32
|
|
*/
|
|
internals.rfc3986.cidr = digitOnly + or + '[1-2]' + digitOnly + or + '3' + '[0-2]';
|
|
|
|
/**
|
|
* HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
|
|
*/
|
|
var hexDigit = digit + 'A-Fa-f';
|
|
var hexDigitOnly = '[' + hexDigit + ']';
|
|
|
|
/**
|
|
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
|
*/
|
|
var unreserved = alpha + digit + '-\\._~';
|
|
|
|
/**
|
|
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
|
*/
|
|
var subDelims = '!\\$&\'\\(\\)\\*\\+,;=';
|
|
|
|
/**
|
|
* pct-encoded = "%" HEXDIG HEXDIG
|
|
*/
|
|
var pctEncoded = '%' + hexDigit;
|
|
|
|
/**
|
|
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
|
*/
|
|
var pchar = unreserved + pctEncoded + subDelims + ':@';
|
|
var pcharOnly = '[' + pchar + ']';
|
|
|
|
/**
|
|
* Rule to support zero-padded addresses.
|
|
*/
|
|
var zeroPad = '0?';
|
|
|
|
/**
|
|
* dec-octet = DIGIT ; 0-9
|
|
* / %x31-39 DIGIT ; 10-99
|
|
* / "1" 2DIGIT ; 100-199
|
|
* / "2" %x30-34 DIGIT ; 200-249
|
|
* / "25" %x30-35 ; 250-255
|
|
*/
|
|
var decOctect = '(?:' + zeroPad + zeroPad + digitOnly + or + zeroPad + '[1-9]' + digitOnly + or + '1' + digitOnly + digitOnly + or + '2' + '[0-4]' + digitOnly + or + '25' + '[0-5])';
|
|
|
|
/**
|
|
* IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
|
|
*/
|
|
internals.rfc3986.IPv4address = '(?:' + decOctect + '\\.){3}' + decOctect;
|
|
|
|
/**
|
|
* h16 = 1*4HEXDIG ; 16 bits of address represented in hexadecimal
|
|
* ls32 = ( h16 ":" h16 ) / IPv4address ; least-significant 32 bits of address
|
|
* IPv6address = 6( h16 ":" ) ls32
|
|
* / "::" 5( h16 ":" ) ls32
|
|
* / [ h16 ] "::" 4( h16 ":" ) ls32
|
|
* / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
|
|
* / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
|
|
* / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
|
|
* / [ *4( h16 ":" ) h16 ] "::" ls32
|
|
* / [ *5( h16 ":" ) h16 ] "::" h16
|
|
* / [ *6( h16 ":" ) h16 ] "::"
|
|
*/
|
|
var h16 = hexDigitOnly + '{1,4}';
|
|
var ls32 = '(?:' + h16 + ':' + h16 + '|' + internals.rfc3986.IPv4address + ')';
|
|
var IPv6SixHex = '(?:' + h16 + ':){6}' + ls32;
|
|
var IPv6FiveHex = '::(?:' + h16 + ':){5}' + ls32;
|
|
var IPv6FourHex = '(?:' + h16 + ')?::(?:' + h16 + ':){4}' + ls32;
|
|
var IPv6ThreeHex = '(?:(?:' + h16 + ':){0,1}' + h16 + ')?::(?:' + h16 + ':){3}' + ls32;
|
|
var IPv6TwoHex = '(?:(?:' + h16 + ':){0,2}' + h16 + ')?::(?:' + h16 + ':){2}' + ls32;
|
|
var IPv6OneHex = '(?:(?:' + h16 + ':){0,3}' + h16 + ')?::' + h16 + ':' + ls32;
|
|
var IPv6NoneHex = '(?:(?:' + h16 + ':){0,4}' + h16 + ')?::' + ls32;
|
|
var IPv6NoneHex2 = '(?:(?:' + h16 + ':){0,5}' + h16 + ')?::' + h16;
|
|
var IPv6NoneHex3 = '(?:(?:' + h16 + ':){0,6}' + h16 + ')?::';
|
|
internals.rfc3986.IPv6address = '(?:' + IPv6SixHex + or + IPv6FiveHex + or + IPv6FourHex + or + IPv6ThreeHex + or + IPv6TwoHex + or + IPv6OneHex + or + IPv6NoneHex + or + IPv6NoneHex2 + or + IPv6NoneHex3 + ')';
|
|
|
|
/**
|
|
* IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
|
|
*/
|
|
internals.rfc3986.IPvFuture = 'v' + hexDigitOnly + '+\\.[' + unreserved + subDelims + ':]+';
|
|
|
|
/**
|
|
* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
|
|
*/
|
|
internals.rfc3986.scheme = alphaOnly + '[' + alpha + digit + '+-\\.]*';
|
|
|
|
/**
|
|
* userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
|
|
*/
|
|
var userinfo = '[' + unreserved + pctEncoded + subDelims + ':]*';
|
|
|
|
/**
|
|
* IP-literal = "[" ( IPv6address / IPvFuture ) "]"
|
|
*/
|
|
internals.rfc3986.IPLiteral = '\\[(?:' + internals.rfc3986.IPv6address + or + internals.rfc3986.IPvFuture + ')\\]';
|
|
|
|
/**
|
|
* reg-name = *( unreserved / pct-encoded / sub-delims )
|
|
*/
|
|
var regName = '[' + unreserved + pctEncoded + subDelims + ']{0,255}';
|
|
|
|
/**
|
|
* host = IP-literal / IPv4address / reg-name
|
|
*/
|
|
var host = '(?:' + internals.rfc3986.IPLiteral + or + internals.rfc3986.IPv4address + or + regName + ')';
|
|
|
|
/**
|
|
* port = *DIGIT
|
|
*/
|
|
var port = digitOnly + '*';
|
|
|
|
/**
|
|
* authority = [ userinfo "@" ] host [ ":" port ]
|
|
*/
|
|
var authority = '(?:' + userinfo + '@)?' + host + '(?::' + port + ')?';
|
|
|
|
/**
|
|
* segment = *pchar
|
|
* segment-nz = 1*pchar
|
|
* path = path-abempty ; begins with "/" or is empty
|
|
* / path-absolute ; begins with "/" but not "//"
|
|
* / path-noscheme ; begins with a non-colon segment
|
|
* / path-rootless ; begins with a segment
|
|
* / path-empty ; zero characters
|
|
* path-abempty = *( "/" segment )
|
|
* path-absolute = "/" [ segment-nz *( "/" segment ) ]
|
|
* path-rootless = segment-nz *( "/" segment )
|
|
*/
|
|
var segment = pcharOnly + '*';
|
|
var segmentNz = pcharOnly + '+';
|
|
var pathAbEmpty = '(?:\\/' + segment + ')*';
|
|
var pathAbsolute = '\\/(?:' + segmentNz + pathAbEmpty + ')?';
|
|
var pathRootless = segmentNz + pathAbEmpty;
|
|
|
|
/**
|
|
* hier-part = "//" authority path
|
|
*/
|
|
internals.rfc3986.hierPart = '(?:' + '(?:\\/\\/' + authority + pathAbEmpty + ')' + or + pathAbsolute + or + pathRootless + ')';
|
|
|
|
/**
|
|
* query = *( pchar / "/" / "?" )
|
|
*/
|
|
internals.rfc3986.query = '[' + pchar + '\\/\\?]*(?=#|$)'; //Finish matching either at the fragment part or end of the line.
|
|
|
|
/**
|
|
* fragment = *( pchar / "/" / "?" )
|
|
*/
|
|
internals.rfc3986.fragment = '[' + pchar + '\\/\\?]*';
|
|
|
|
/**
|
|
* URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
|
|
*
|
|
* OR
|
|
*
|
|
* relative-ref = relative-part [ "?" query ] [ "#" fragment ]
|
|
*/
|
|
internals.rfc3986.uri = '^(?:' + internals.rfc3986.scheme + ':' + internals.rfc3986.hierPart + ')(?:\\?' + internals.rfc3986.query + ')?' + '(?:#' + internals.rfc3986.fragment + ')?$';
|
|
};
|
|
|
|
internals.generate();
|
|
|
|
module.exports = internals.rfc3986;
|
|
|
|
/***/ }),
|
|
/* 179 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var path = __webpack_require__(57);
|
|
var fs = __webpack_require__(55);
|
|
var _0777 = parseInt('0777', 8);
|
|
|
|
module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
|
|
|
|
function mkdirP (p, opts, f, made) {
|
|
if (typeof opts === 'function') {
|
|
f = opts;
|
|
opts = {};
|
|
}
|
|
else if (!opts || typeof opts !== 'object') {
|
|
opts = { mode: opts };
|
|
}
|
|
|
|
var mode = opts.mode;
|
|
var xfs = opts.fs || fs;
|
|
|
|
if (mode === undefined) {
|
|
mode = _0777 & (~process.umask());
|
|
}
|
|
if (!made) made = null;
|
|
|
|
var cb = f || function () {};
|
|
p = path.resolve(p);
|
|
|
|
xfs.mkdir(p, mode, function (er) {
|
|
if (!er) {
|
|
made = made || p;
|
|
return cb(null, made);
|
|
}
|
|
switch (er.code) {
|
|
case 'ENOENT':
|
|
mkdirP(path.dirname(p), opts, function (er, made) {
|
|
if (er) cb(er, made);
|
|
else mkdirP(p, opts, cb, made);
|
|
});
|
|
break;
|
|
|
|
// In the case of any other error, just see if there's a dir
|
|
// there already. If so, then hooray! If not, then something
|
|
// is borked.
|
|
default:
|
|
xfs.stat(p, function (er2, stat) {
|
|
// if the stat fails, then that's super weird.
|
|
// let the original error be the failure reason.
|
|
if (er2 || !stat.isDirectory()) cb(er, made)
|
|
else cb(null, made);
|
|
});
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
|
|
mkdirP.sync = function sync (p, opts, made) {
|
|
if (!opts || typeof opts !== 'object') {
|
|
opts = { mode: opts };
|
|
}
|
|
|
|
var mode = opts.mode;
|
|
var xfs = opts.fs || fs;
|
|
|
|
if (mode === undefined) {
|
|
mode = _0777 & (~process.umask());
|
|
}
|
|
if (!made) made = null;
|
|
|
|
p = path.resolve(p);
|
|
|
|
try {
|
|
xfs.mkdirSync(p, mode);
|
|
made = made || p;
|
|
}
|
|
catch (err0) {
|
|
switch (err0.code) {
|
|
case 'ENOENT' :
|
|
made = sync(path.dirname(p), opts, made);
|
|
sync(p, opts, made);
|
|
break;
|
|
|
|
// In the case of any other error, just see if there's a dir
|
|
// there already. If so, then hooray! If not, then something
|
|
// is borked.
|
|
default:
|
|
var stat;
|
|
try {
|
|
stat = xfs.statSync(p);
|
|
}
|
|
catch (err1) {
|
|
throw err0;
|
|
}
|
|
if (!stat.isDirectory()) throw err0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return made;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 180 */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "setUriThrowOnMissingScheme", function() { return setUriThrowOnMissingScheme; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "URI", function() { return URI; });
|
|
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
var __extends = (undefined && undefined.__extends) || (function () {
|
|
var extendStatics = Object.setPrototypeOf ||
|
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
|
return function (d, b) {
|
|
extendStatics(d, b);
|
|
function __() { this.constructor = d; }
|
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
};
|
|
})();
|
|
var isWindows;
|
|
if (typeof process === 'object') {
|
|
isWindows = process.platform === 'win32';
|
|
}
|
|
else if (typeof navigator === 'object') {
|
|
var userAgent = navigator.userAgent;
|
|
isWindows = userAgent.indexOf('Windows') >= 0;
|
|
}
|
|
//#endregion
|
|
var _schemePattern = /^\w[\w\d+.-]*$/;
|
|
var _singleSlashStart = /^\//;
|
|
var _doubleSlashStart = /^\/\//;
|
|
var _throwOnMissingSchema = true;
|
|
/**
|
|
* @internal
|
|
*/
|
|
function setUriThrowOnMissingScheme(value) {
|
|
var old = _throwOnMissingSchema;
|
|
_throwOnMissingSchema = value;
|
|
return old;
|
|
}
|
|
function _validateUri(ret, _strict) {
|
|
// scheme, must be set
|
|
if (!ret.scheme) {
|
|
if (_strict || _throwOnMissingSchema) {
|
|
throw new Error("[UriError]: Scheme is missing: {scheme: \"\", authority: \"" + ret.authority + "\", path: \"" + ret.path + "\", query: \"" + ret.query + "\", fragment: \"" + ret.fragment + "\"}");
|
|
}
|
|
else {
|
|
// console.warn(`[UriError]: Scheme is missing: {scheme: "", authority: "${ret.authority}", path: "${ret.path}", query: "${ret.query}", fragment: "${ret.fragment}"}`);
|
|
}
|
|
}
|
|
// scheme, https://tools.ietf.org/html/rfc3986#section-3.1
|
|
// ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
|
|
if (ret.scheme && !_schemePattern.test(ret.scheme)) {
|
|
throw new Error('[UriError]: Scheme contains illegal characters.');
|
|
}
|
|
// path, http://tools.ietf.org/html/rfc3986#section-3.3
|
|
// If a URI contains an authority component, then the path component
|
|
// must either be empty or begin with a slash ("/") character. If a URI
|
|
// does not contain an authority component, then the path cannot begin
|
|
// with two slash characters ("//").
|
|
if (ret.path) {
|
|
if (ret.authority) {
|
|
if (!_singleSlashStart.test(ret.path)) {
|
|
throw new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character');
|
|
}
|
|
}
|
|
else {
|
|
if (_doubleSlashStart.test(ret.path)) {
|
|
throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters ("//")');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// for a while we allowed uris *without* schemes and this is the migration
|
|
// for them, e.g. an uri without scheme and without strict-mode warns and falls
|
|
// back to the file-scheme. that should cause the least carnage and still be a
|
|
// clear warning
|
|
function _schemeFix(scheme, _strict) {
|
|
if (_strict || _throwOnMissingSchema) {
|
|
return scheme || _empty;
|
|
}
|
|
if (!scheme) {
|
|
// console.trace('BAD uri lacks scheme, falling back to file-scheme.');
|
|
scheme = 'file';
|
|
}
|
|
return scheme;
|
|
}
|
|
// implements a bit of https://tools.ietf.org/html/rfc3986#section-5
|
|
function _referenceResolution(scheme, path) {
|
|
// the slash-character is our 'default base' as we don't
|
|
// support constructing URIs relative to other URIs. This
|
|
// also means that we alter and potentially break paths.
|
|
// see https://tools.ietf.org/html/rfc3986#section-5.1.4
|
|
switch (scheme) {
|
|
case 'https':
|
|
case 'http':
|
|
case 'file':
|
|
if (!path) {
|
|
path = _slash;
|
|
}
|
|
else if (path[0] !== _slash) {
|
|
path = _slash + path;
|
|
}
|
|
break;
|
|
}
|
|
return path;
|
|
}
|
|
var _empty = '';
|
|
var _slash = '/';
|
|
var _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
|
|
/**
|
|
* Uniform Resource Identifier (URI) http://tools.ietf.org/html/rfc3986.
|
|
* This class is a simple parser which creates the basic component parts
|
|
* (http://tools.ietf.org/html/rfc3986#section-3) with minimal validation
|
|
* and encoding.
|
|
*
|
|
* foo://example.com:8042/over/there?name=ferret#nose
|
|
* \_/ \______________/\_________/ \_________/ \__/
|
|
* | | | | |
|
|
* scheme authority path query fragment
|
|
* | _____________________|__
|
|
* / \ / \
|
|
* urn:example:animal:ferret:nose
|
|
*/
|
|
var URI = (function () {
|
|
/**
|
|
* @internal
|
|
*/
|
|
function URI(schemeOrData, authority, path, query, fragment, _strict) {
|
|
if (_strict === void 0) { _strict = false; }
|
|
if (typeof schemeOrData === 'object') {
|
|
this.scheme = schemeOrData.scheme || _empty;
|
|
this.authority = schemeOrData.authority || _empty;
|
|
this.path = schemeOrData.path || _empty;
|
|
this.query = schemeOrData.query || _empty;
|
|
this.fragment = schemeOrData.fragment || _empty;
|
|
// no validation because it's this URI
|
|
// that creates uri components.
|
|
// _validateUri(this);
|
|
}
|
|
else {
|
|
this.scheme = _schemeFix(schemeOrData, _strict);
|
|
this.authority = authority || _empty;
|
|
this.path = _referenceResolution(this.scheme, path || _empty);
|
|
this.query = query || _empty;
|
|
this.fragment = fragment || _empty;
|
|
_validateUri(this, _strict);
|
|
}
|
|
}
|
|
URI.isUri = function (thing) {
|
|
if (thing instanceof URI) {
|
|
return true;
|
|
}
|
|
if (!thing) {
|
|
return false;
|
|
}
|
|
return typeof thing.authority === 'string'
|
|
&& typeof thing.fragment === 'string'
|
|
&& typeof thing.path === 'string'
|
|
&& typeof thing.query === 'string'
|
|
&& typeof thing.scheme === 'string'
|
|
&& typeof thing.fsPath === 'function'
|
|
&& typeof thing.with === 'function'
|
|
&& typeof thing.toString === 'function';
|
|
};
|
|
Object.defineProperty(URI.prototype, "fsPath", {
|
|
// ---- filesystem path -----------------------
|
|
/**
|
|
* Returns a string representing the corresponding file system path of this URI.
|
|
* Will handle UNC paths, normalizes windows drive letters to lower-case, and uses the
|
|
* platform specific path separator.
|
|
*
|
|
* * Will *not* validate the path for invalid characters and semantics.
|
|
* * Will *not* look at the scheme of this URI.
|
|
* * The result shall *not* be used for display purposes but for accessing a file on disk.
|
|
*
|
|
*
|
|
* The *difference* to `URI#path` is the use of the platform specific separator and the handling
|
|
* of UNC paths. See the below sample of a file-uri with an authority (UNC path).
|
|
*
|
|
* ```ts
|
|
const u = URI.parse('file://server/c$/folder/file.txt')
|
|
u.authority === 'server'
|
|
u.path === '/shares/c$/file.txt'
|
|
u.fsPath === '\\server\c$\folder\file.txt'
|
|
```
|
|
*
|
|
* Using `URI#path` to read a file (using fs-apis) would not be enough because parts of the path,
|
|
* namely the server name, would be missing. Therefore `URI#fsPath` exists - it's sugar to ease working
|
|
* with URIs that represent files on disk (`file` scheme).
|
|
*/
|
|
get: function () {
|
|
// if (this.scheme !== 'file') {
|
|
// console.warn(`[UriError] calling fsPath with scheme ${this.scheme}`);
|
|
// }
|
|
return _makeFsPath(this);
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
});
|
|
// ---- modify to new -------------------------
|
|
URI.prototype.with = function (change) {
|
|
if (!change) {
|
|
return this;
|
|
}
|
|
var scheme = change.scheme, authority = change.authority, path = change.path, query = change.query, fragment = change.fragment;
|
|
if (scheme === undefined) {
|
|
scheme = this.scheme;
|
|
}
|
|
else if (scheme === null) {
|
|
scheme = _empty;
|
|
}
|
|
if (authority === undefined) {
|
|
authority = this.authority;
|
|
}
|
|
else if (authority === null) {
|
|
authority = _empty;
|
|
}
|
|
if (path === undefined) {
|
|
path = this.path;
|
|
}
|
|
else if (path === null) {
|
|
path = _empty;
|
|
}
|
|
if (query === undefined) {
|
|
query = this.query;
|
|
}
|
|
else if (query === null) {
|
|
query = _empty;
|
|
}
|
|
if (fragment === undefined) {
|
|
fragment = this.fragment;
|
|
}
|
|
else if (fragment === null) {
|
|
fragment = _empty;
|
|
}
|
|
if (scheme === this.scheme
|
|
&& authority === this.authority
|
|
&& path === this.path
|
|
&& query === this.query
|
|
&& fragment === this.fragment) {
|
|
return this;
|
|
}
|
|
return new _URI(scheme, authority, path, query, fragment);
|
|
};
|
|
// ---- parse & validate ------------------------
|
|
/**
|
|
* Creates a new URI from a string, e.g. `http://www.msft.com/some/path`,
|
|
* `file:///usr/home`, or `scheme:with/path`.
|
|
*
|
|
* @param value A string which represents an URI (see `URI#toString`).
|
|
*/
|
|
URI.parse = function (value, _strict) {
|
|
if (_strict === void 0) { _strict = false; }
|
|
var match = _regexp.exec(value);
|
|
if (!match) {
|
|
return new _URI(_empty, _empty, _empty, _empty, _empty);
|
|
}
|
|
return new _URI(match[2] || _empty, decodeURIComponent(match[4] || _empty), decodeURIComponent(match[5] || _empty), decodeURIComponent(match[7] || _empty), decodeURIComponent(match[9] || _empty), _strict);
|
|
};
|
|
/**
|
|
* Creates a new URI from a file system path, e.g. `c:\my\files`,
|
|
* `/usr/home`, or `\\server\share\some\path`.
|
|
*
|
|
* The *difference* between `URI#parse` and `URI#file` is that the latter treats the argument
|
|
* as path, not as stringified-uri. E.g. `URI.file(path)` is **not the same as**
|
|
* `URI.parse('file://' + path)` because the path might contain characters that are
|
|
* interpreted (# and ?). See the following sample:
|
|
* ```ts
|
|
const good = URI.file('/coding/c#/project1');
|
|
good.scheme === 'file';
|
|
good.path === '/coding/c#/project1';
|
|
good.fragment === '';
|
|
const bad = URI.parse('file://' + '/coding/c#/project1');
|
|
bad.scheme === 'file';
|
|
bad.path === '/coding/c'; // path is now broken
|
|
bad.fragment === '/project1';
|
|
```
|
|
*
|
|
* @param path A file system path (see `URI#fsPath`)
|
|
*/
|
|
URI.file = function (path) {
|
|
var authority = _empty;
|
|
// normalize to fwd-slashes on windows,
|
|
// on other systems bwd-slashes are valid
|
|
// filename character, eg /f\oo/ba\r.txt
|
|
if (isWindows) {
|
|
path = path.replace(/\\/g, _slash);
|
|
}
|
|
// check for authority as used in UNC shares
|
|
// or use the path as given
|
|
if (path[0] === _slash && path[1] === _slash) {
|
|
var idx = path.indexOf(_slash, 2);
|
|
if (idx === -1) {
|
|
authority = path.substring(2);
|
|
path = _slash;
|
|
}
|
|
else {
|
|
authority = path.substring(2, idx);
|
|
path = path.substring(idx) || _slash;
|
|
}
|
|
}
|
|
return new _URI('file', authority, path, _empty, _empty);
|
|
};
|
|
URI.from = function (components) {
|
|
return new _URI(components.scheme, components.authority, components.path, components.query, components.fragment);
|
|
};
|
|
// ---- printing/externalize ---------------------------
|
|
/**
|
|
* Creates a string representation for this URI. It's guaranteed that calling
|
|
* `URI.parse` with the result of this function creates an URI which is equal
|
|
* to this URI.
|
|
*
|
|
* * The result shall *not* be used for display purposes but for externalization or transport.
|
|
* * The result will be encoded using the percentage encoding and encoding happens mostly
|
|
* ignore the scheme-specific encoding rules.
|
|
*
|
|
* @param skipEncoding Do not encode the result, default is `false`
|
|
*/
|
|
URI.prototype.toString = function (skipEncoding) {
|
|
if (skipEncoding === void 0) { skipEncoding = false; }
|
|
return _asFormatted(this, skipEncoding);
|
|
};
|
|
URI.prototype.toJSON = function () {
|
|
return this;
|
|
};
|
|
URI.revive = function (data) {
|
|
if (!data) {
|
|
return data;
|
|
}
|
|
else if (data instanceof URI) {
|
|
return data;
|
|
}
|
|
else {
|
|
var result = new _URI(data);
|
|
result._formatted = data.external;
|
|
result._fsPath = data._sep === _pathSepMarker ? data.fsPath : null;
|
|
return result;
|
|
}
|
|
};
|
|
return URI;
|
|
}());
|
|
|
|
var _pathSepMarker = isWindows ? 1 : undefined;
|
|
// tslint:disable-next-line:class-name
|
|
var _URI = (function (_super) {
|
|
__extends(_URI, _super);
|
|
function _URI() {
|
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
_this._formatted = null;
|
|
_this._fsPath = null;
|
|
return _this;
|
|
}
|
|
Object.defineProperty(_URI.prototype, "fsPath", {
|
|
get: function () {
|
|
if (!this._fsPath) {
|
|
this._fsPath = _makeFsPath(this);
|
|
}
|
|
return this._fsPath;
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
});
|
|
_URI.prototype.toString = function (skipEncoding) {
|
|
if (skipEncoding === void 0) { skipEncoding = false; }
|
|
if (!skipEncoding) {
|
|
if (!this._formatted) {
|
|
this._formatted = _asFormatted(this, false);
|
|
}
|
|
return this._formatted;
|
|
}
|
|
else {
|
|
// we don't cache that
|
|
return _asFormatted(this, true);
|
|
}
|
|
};
|
|
_URI.prototype.toJSON = function () {
|
|
var res = {
|
|
$mid: 1
|
|
};
|
|
// cached state
|
|
if (this._fsPath) {
|
|
res.fsPath = this._fsPath;
|
|
res._sep = _pathSepMarker;
|
|
}
|
|
if (this._formatted) {
|
|
res.external = this._formatted;
|
|
}
|
|
// uri components
|
|
if (this.path) {
|
|
res.path = this.path;
|
|
}
|
|
if (this.scheme) {
|
|
res.scheme = this.scheme;
|
|
}
|
|
if (this.authority) {
|
|
res.authority = this.authority;
|
|
}
|
|
if (this.query) {
|
|
res.query = this.query;
|
|
}
|
|
if (this.fragment) {
|
|
res.fragment = this.fragment;
|
|
}
|
|
return res;
|
|
};
|
|
return _URI;
|
|
}(URI));
|
|
// reserved characters: https://tools.ietf.org/html/rfc3986#section-2.2
|
|
var encodeTable = (_a = {},
|
|
_a[58 /* Colon */] = '%3A',
|
|
_a[47 /* Slash */] = '%2F',
|
|
_a[63 /* QuestionMark */] = '%3F',
|
|
_a[35 /* Hash */] = '%23',
|
|
_a[91 /* OpenSquareBracket */] = '%5B',
|
|
_a[93 /* CloseSquareBracket */] = '%5D',
|
|
_a[64 /* AtSign */] = '%40',
|
|
_a[33 /* ExclamationMark */] = '%21',
|
|
_a[36 /* DollarSign */] = '%24',
|
|
_a[38 /* Ampersand */] = '%26',
|
|
_a[39 /* SingleQuote */] = '%27',
|
|
_a[40 /* OpenParen */] = '%28',
|
|
_a[41 /* CloseParen */] = '%29',
|
|
_a[42 /* Asterisk */] = '%2A',
|
|
_a[43 /* Plus */] = '%2B',
|
|
_a[44 /* Comma */] = '%2C',
|
|
_a[59 /* Semicolon */] = '%3B',
|
|
_a[61 /* Equals */] = '%3D',
|
|
_a[32 /* Space */] = '%20',
|
|
_a);
|
|
function encodeURIComponentFast(uriComponent, allowSlash) {
|
|
var res = undefined;
|
|
var nativeEncodePos = -1;
|
|
for (var pos = 0; pos < uriComponent.length; pos++) {
|
|
var code = uriComponent.charCodeAt(pos);
|
|
// unreserved characters: https://tools.ietf.org/html/rfc3986#section-2.3
|
|
if ((code >= 97 /* a */ && code <= 122 /* z */)
|
|
|| (code >= 65 /* A */ && code <= 90 /* Z */)
|
|
|| (code >= 48 /* Digit0 */ && code <= 57 /* Digit9 */)
|
|
|| code === 45 /* Dash */
|
|
|| code === 46 /* Period */
|
|
|| code === 95 /* Underline */
|
|
|| code === 126 /* Tilde */
|
|
|| (allowSlash && code === 47 /* Slash */)) {
|
|
// check if we are delaying native encode
|
|
if (nativeEncodePos !== -1) {
|
|
res += encodeURIComponent(uriComponent.substring(nativeEncodePos, pos));
|
|
nativeEncodePos = -1;
|
|
}
|
|
// check if we write into a new string (by default we try to return the param)
|
|
if (res !== undefined) {
|
|
res += uriComponent.charAt(pos);
|
|
}
|
|
}
|
|
else {
|
|
// encoding needed, we need to allocate a new string
|
|
if (res === undefined) {
|
|
res = uriComponent.substr(0, pos);
|
|
}
|
|
// check with default table first
|
|
var escaped = encodeTable[code];
|
|
if (escaped !== undefined) {
|
|
// check if we are delaying native encode
|
|
if (nativeEncodePos !== -1) {
|
|
res += encodeURIComponent(uriComponent.substring(nativeEncodePos, pos));
|
|
nativeEncodePos = -1;
|
|
}
|
|
// append escaped variant to result
|
|
res += escaped;
|
|
}
|
|
else if (nativeEncodePos === -1) {
|
|
// use native encode only when needed
|
|
nativeEncodePos = pos;
|
|
}
|
|
}
|
|
}
|
|
if (nativeEncodePos !== -1) {
|
|
res += encodeURIComponent(uriComponent.substring(nativeEncodePos));
|
|
}
|
|
return res !== undefined ? res : uriComponent;
|
|
}
|
|
function encodeURIComponentMinimal(path) {
|
|
var res = undefined;
|
|
for (var pos = 0; pos < path.length; pos++) {
|
|
var code = path.charCodeAt(pos);
|
|
if (code === 35 /* Hash */ || code === 63 /* QuestionMark */) {
|
|
if (res === undefined) {
|
|
res = path.substr(0, pos);
|
|
}
|
|
res += encodeTable[code];
|
|
}
|
|
else {
|
|
if (res !== undefined) {
|
|
res += path[pos];
|
|
}
|
|
}
|
|
}
|
|
return res !== undefined ? res : path;
|
|
}
|
|
/**
|
|
* Compute `fsPath` for the given uri
|
|
*/
|
|
function _makeFsPath(uri) {
|
|
var value;
|
|
if (uri.authority && uri.path.length > 1 && uri.scheme === 'file') {
|
|
// unc path: file://shares/c$/far/boo
|
|
value = "//" + uri.authority + uri.path;
|
|
}
|
|
else if (uri.path.charCodeAt(0) === 47 /* Slash */
|
|
&& (uri.path.charCodeAt(1) >= 65 /* A */ && uri.path.charCodeAt(1) <= 90 /* Z */ || uri.path.charCodeAt(1) >= 97 /* a */ && uri.path.charCodeAt(1) <= 122 /* z */)
|
|
&& uri.path.charCodeAt(2) === 58 /* Colon */) {
|
|
// windows drive letter: file:///c:/far/boo
|
|
value = uri.path[1].toLowerCase() + uri.path.substr(2);
|
|
}
|
|
else {
|
|
// other path
|
|
value = uri.path;
|
|
}
|
|
if (isWindows) {
|
|
value = value.replace(/\//g, '\\');
|
|
}
|
|
return value;
|
|
}
|
|
/**
|
|
* Create the external version of a uri
|
|
*/
|
|
function _asFormatted(uri, skipEncoding) {
|
|
var encoder = !skipEncoding
|
|
? encodeURIComponentFast
|
|
: encodeURIComponentMinimal;
|
|
var res = '';
|
|
var scheme = uri.scheme, authority = uri.authority, path = uri.path, query = uri.query, fragment = uri.fragment;
|
|
if (scheme) {
|
|
res += scheme;
|
|
res += ':';
|
|
}
|
|
if (authority || scheme === 'file') {
|
|
res += _slash;
|
|
res += _slash;
|
|
}
|
|
if (authority) {
|
|
var idx = authority.indexOf('@');
|
|
if (idx !== -1) {
|
|
// <user>@<auth>
|
|
var userinfo = authority.substr(0, idx);
|
|
authority = authority.substr(idx + 1);
|
|
idx = userinfo.indexOf(':');
|
|
if (idx === -1) {
|
|
res += encoder(userinfo, false);
|
|
}
|
|
else {
|
|
// <user>:<pass>@<auth>
|
|
res += encoder(userinfo.substr(0, idx), false);
|
|
res += ':';
|
|
res += encoder(userinfo.substr(idx + 1), false);
|
|
}
|
|
res += '@';
|
|
}
|
|
authority = authority.toLowerCase();
|
|
idx = authority.indexOf(':');
|
|
if (idx === -1) {
|
|
res += encoder(authority, false);
|
|
}
|
|
else {
|
|
// <auth>:<port>
|
|
res += encoder(authority.substr(0, idx), false);
|
|
res += authority.substr(idx);
|
|
}
|
|
}
|
|
if (path) {
|
|
// lower-case windows drive letters in /C:/fff or C:/fff
|
|
if (path.length >= 3 && path.charCodeAt(0) === 47 /* Slash */ && path.charCodeAt(2) === 58 /* Colon */) {
|
|
var code = path.charCodeAt(1);
|
|
if (code >= 65 /* A */ && code <= 90 /* Z */) {
|
|
path = "/" + String.fromCharCode(code + 32) + ":" + path.substr(3); // "/c:".length === 3
|
|
}
|
|
}
|
|
else if (path.length >= 2 && path.charCodeAt(1) === 58 /* Colon */) {
|
|
var code = path.charCodeAt(0);
|
|
if (code >= 65 /* A */ && code <= 90 /* Z */) {
|
|
path = String.fromCharCode(code + 32) + ":" + path.substr(2); // "/c:".length === 3
|
|
}
|
|
}
|
|
// encode the rest of the path
|
|
res += encoder(path, true);
|
|
}
|
|
if (query) {
|
|
res += '?';
|
|
res += encoder(query, false);
|
|
}
|
|
if (fragment) {
|
|
res += '#';
|
|
res += !skipEncoding ? encodeURIComponentFast(fragment, false) : fragment;
|
|
}
|
|
return res;
|
|
}
|
|
var _a;
|
|
|
|
|
|
/***/ }),
|
|
/* 181 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
module.exports = which
|
|
which.sync = whichSync
|
|
|
|
var isWindows = process.platform === 'win32' ||
|
|
process.env.OSTYPE === 'cygwin' ||
|
|
process.env.OSTYPE === 'msys'
|
|
|
|
var path = __webpack_require__(57)
|
|
var COLON = isWindows ? ';' : ':'
|
|
var isexe = __webpack_require__(182)
|
|
|
|
function getNotFoundError (cmd) {
|
|
var er = new Error('not found: ' + cmd)
|
|
er.code = 'ENOENT'
|
|
|
|
return er
|
|
}
|
|
|
|
function getPathInfo (cmd, opt) {
|
|
var colon = opt.colon || COLON
|
|
var pathEnv = opt.path || process.env.PATH || ''
|
|
var pathExt = ['']
|
|
|
|
pathEnv = pathEnv.split(colon)
|
|
|
|
var pathExtExe = ''
|
|
if (isWindows) {
|
|
pathEnv.unshift(process.cwd())
|
|
pathExtExe = (opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM')
|
|
pathExt = pathExtExe.split(colon)
|
|
|
|
|
|
// Always test the cmd itself first. isexe will check to make sure
|
|
// it's found in the pathExt set.
|
|
if (cmd.indexOf('.') !== -1 && pathExt[0] !== '')
|
|
pathExt.unshift('')
|
|
}
|
|
|
|
// If it has a slash, then we don't bother searching the pathenv.
|
|
// just check the file itself, and that's it.
|
|
if (cmd.match(/\//) || isWindows && cmd.match(/\\/))
|
|
pathEnv = ['']
|
|
|
|
return {
|
|
env: pathEnv,
|
|
ext: pathExt,
|
|
extExe: pathExtExe
|
|
}
|
|
}
|
|
|
|
function which (cmd, opt, cb) {
|
|
if (typeof opt === 'function') {
|
|
cb = opt
|
|
opt = {}
|
|
}
|
|
|
|
var info = getPathInfo(cmd, opt)
|
|
var pathEnv = info.env
|
|
var pathExt = info.ext
|
|
var pathExtExe = info.extExe
|
|
var found = []
|
|
|
|
;(function F (i, l) {
|
|
if (i === l) {
|
|
if (opt.all && found.length)
|
|
return cb(null, found)
|
|
else
|
|
return cb(getNotFoundError(cmd))
|
|
}
|
|
|
|
var pathPart = pathEnv[i]
|
|
if (pathPart.charAt(0) === '"' && pathPart.slice(-1) === '"')
|
|
pathPart = pathPart.slice(1, -1)
|
|
|
|
var p = path.join(pathPart, cmd)
|
|
if (!pathPart && (/^\.[\\\/]/).test(cmd)) {
|
|
p = cmd.slice(0, 2) + p
|
|
}
|
|
;(function E (ii, ll) {
|
|
if (ii === ll) return F(i + 1, l)
|
|
var ext = pathExt[ii]
|
|
isexe(p + ext, { pathExt: pathExtExe }, function (er, is) {
|
|
if (!er && is) {
|
|
if (opt.all)
|
|
found.push(p + ext)
|
|
else
|
|
return cb(null, p + ext)
|
|
}
|
|
return E(ii + 1, ll)
|
|
})
|
|
})(0, pathExt.length)
|
|
})(0, pathEnv.length)
|
|
}
|
|
|
|
function whichSync (cmd, opt) {
|
|
opt = opt || {}
|
|
|
|
var info = getPathInfo(cmd, opt)
|
|
var pathEnv = info.env
|
|
var pathExt = info.ext
|
|
var pathExtExe = info.extExe
|
|
var found = []
|
|
|
|
for (var i = 0, l = pathEnv.length; i < l; i ++) {
|
|
var pathPart = pathEnv[i]
|
|
if (pathPart.charAt(0) === '"' && pathPart.slice(-1) === '"')
|
|
pathPart = pathPart.slice(1, -1)
|
|
|
|
var p = path.join(pathPart, cmd)
|
|
if (!pathPart && /^\.[\\\/]/.test(cmd)) {
|
|
p = cmd.slice(0, 2) + p
|
|
}
|
|
for (var j = 0, ll = pathExt.length; j < ll; j ++) {
|
|
var cur = p + pathExt[j]
|
|
var is
|
|
try {
|
|
is = isexe.sync(cur, { pathExt: pathExtExe })
|
|
if (is) {
|
|
if (opt.all)
|
|
found.push(cur)
|
|
else
|
|
return cur
|
|
}
|
|
} catch (ex) {}
|
|
}
|
|
}
|
|
|
|
if (opt.all && found.length)
|
|
return found
|
|
|
|
if (opt.nothrow)
|
|
return null
|
|
|
|
throw getNotFoundError(cmd)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 182 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var fs = __webpack_require__(55)
|
|
var core
|
|
if (process.platform === 'win32' || global.TESTING_WINDOWS) {
|
|
core = __webpack_require__(183)
|
|
} else {
|
|
core = __webpack_require__(184)
|
|
}
|
|
|
|
module.exports = isexe
|
|
isexe.sync = sync
|
|
|
|
function isexe (path, options, cb) {
|
|
if (typeof options === 'function') {
|
|
cb = options
|
|
options = {}
|
|
}
|
|
|
|
if (!cb) {
|
|
if (typeof Promise !== 'function') {
|
|
throw new TypeError('callback not provided')
|
|
}
|
|
|
|
return new Promise(function (resolve, reject) {
|
|
isexe(path, options || {}, function (er, is) {
|
|
if (er) {
|
|
reject(er)
|
|
} else {
|
|
resolve(is)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
core(path, options || {}, function (er, is) {
|
|
// ignore EACCES because that just means we aren't allowed to run it
|
|
if (er) {
|
|
if (er.code === 'EACCES' || options && options.ignoreErrors) {
|
|
er = null
|
|
is = false
|
|
}
|
|
}
|
|
cb(er, is)
|
|
})
|
|
}
|
|
|
|
function sync (path, options) {
|
|
// my kingdom for a filtered catch
|
|
try {
|
|
return core.sync(path, options || {})
|
|
} catch (er) {
|
|
if (options && options.ignoreErrors || er.code === 'EACCES') {
|
|
return false
|
|
} else {
|
|
throw er
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 183 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
module.exports = isexe
|
|
isexe.sync = sync
|
|
|
|
var fs = __webpack_require__(55)
|
|
|
|
function checkPathExt (path, options) {
|
|
var pathext = options.pathExt !== undefined ?
|
|
options.pathExt : process.env.PATHEXT
|
|
|
|
if (!pathext) {
|
|
return true
|
|
}
|
|
|
|
pathext = pathext.split(';')
|
|
if (pathext.indexOf('') !== -1) {
|
|
return true
|
|
}
|
|
for (var i = 0; i < pathext.length; i++) {
|
|
var p = pathext[i].toLowerCase()
|
|
if (p && path.substr(-p.length).toLowerCase() === p) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
function checkStat (stat, path, options) {
|
|
if (!stat.isSymbolicLink() && !stat.isFile()) {
|
|
return false
|
|
}
|
|
return checkPathExt(path, options)
|
|
}
|
|
|
|
function isexe (path, options, cb) {
|
|
fs.stat(path, function (er, stat) {
|
|
cb(er, er ? false : checkStat(stat, path, options))
|
|
})
|
|
}
|
|
|
|
function sync (path, options) {
|
|
return checkStat(fs.statSync(path), path, options)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 184 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
module.exports = isexe
|
|
isexe.sync = sync
|
|
|
|
var fs = __webpack_require__(55)
|
|
|
|
function isexe (path, options, cb) {
|
|
fs.stat(path, function (er, stat) {
|
|
cb(er, er ? false : checkStat(stat, options))
|
|
})
|
|
}
|
|
|
|
function sync (path, options) {
|
|
return checkStat(fs.statSync(path), options)
|
|
}
|
|
|
|
function checkStat (stat, options) {
|
|
return stat.isFile() && checkMode(stat, options)
|
|
}
|
|
|
|
function checkMode (stat, options) {
|
|
var mod = stat.mode
|
|
var uid = stat.uid
|
|
var gid = stat.gid
|
|
|
|
var myUid = options.uid !== undefined ?
|
|
options.uid : process.getuid && process.getuid()
|
|
var myGid = options.gid !== undefined ?
|
|
options.gid : process.getgid && process.getgid()
|
|
|
|
var u = parseInt('100', 8)
|
|
var g = parseInt('010', 8)
|
|
var o = parseInt('001', 8)
|
|
var ug = u | g
|
|
|
|
var ret = (mod & o) ||
|
|
(mod & g) && gid === myGid ||
|
|
(mod & u) && uid === myUid ||
|
|
(mod & ug) && myUid === 0
|
|
|
|
return ret
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 185 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
let _isWindows = false;
|
|
let _isMacintosh = false;
|
|
let _isLinux = false;
|
|
let _isNative = false;
|
|
let _isWeb = false;
|
|
exports.language = 'en';
|
|
// OS detection
|
|
if (typeof process === 'object' &&
|
|
typeof process.nextTick === 'function' &&
|
|
typeof process.platform === 'string') {
|
|
_isWindows = process.platform === 'win32';
|
|
_isMacintosh = process.platform === 'darwin';
|
|
_isLinux = process.platform === 'linux';
|
|
_isNative = true;
|
|
}
|
|
var Platform;
|
|
(function (Platform) {
|
|
Platform[Platform["Web"] = 0] = "Web";
|
|
Platform[Platform["Mac"] = 1] = "Mac";
|
|
Platform[Platform["Linux"] = 2] = "Linux";
|
|
Platform[Platform["Windows"] = 3] = "Windows";
|
|
})(Platform = exports.Platform || (exports.Platform = {}));
|
|
let _platform = Platform.Web;
|
|
if (_isNative) {
|
|
if (_isMacintosh) {
|
|
_platform = Platform.Mac;
|
|
}
|
|
else if (_isWindows) {
|
|
_platform = Platform.Windows;
|
|
}
|
|
else if (_isLinux) {
|
|
_platform = Platform.Linux;
|
|
}
|
|
}
|
|
exports.isWindows = _isWindows;
|
|
exports.isMacintosh = _isMacintosh;
|
|
exports.isLinux = _isLinux;
|
|
exports.isNative = _isNative;
|
|
exports.isWeb = _isWeb;
|
|
exports.platform = _platform;
|
|
const _globals = typeof self === 'object'
|
|
? self
|
|
: typeof global === 'object'
|
|
? global
|
|
: {};
|
|
exports.globals = _globals;
|
|
exports.OS = _isMacintosh
|
|
? 2 /* Macintosh */
|
|
: _isWindows
|
|
? 1 /* Windows */
|
|
: 3 /* Linux */;
|
|
//# sourceMappingURL=platform.js.map
|
|
|
|
/***/ }),
|
|
/* 186 */
|
|
/***/ (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__(55));
|
|
const log4js_1 = tslib_1.__importDefault(__webpack_require__(64));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const os_1 = tslib_1.__importDefault(__webpack_require__(56));
|
|
function getLogFile() {
|
|
let file = process.env.NVIM_COC_LOG_FILE;
|
|
if (file)
|
|
return file;
|
|
let dir = process.env.XDG_RUNTIME_DIR;
|
|
if (dir)
|
|
return path_1.default.join(dir, `coc-nvim-${process.pid}.log`);
|
|
return path_1.default.join(os_1.default.tmpdir(), `coc-nvim-${process.pid}.log`);
|
|
}
|
|
const MAX_LOG_SIZE = 1024 * 1024;
|
|
const MAX_LOG_BACKUPS = 10;
|
|
let logfile = getLogFile();
|
|
const level = process.env.NVIM_COC_LOG_LEVEL || 'info';
|
|
if (!fs_1.default.existsSync(logfile)) {
|
|
try {
|
|
fs_1.default.writeFileSync(logfile, '', { encoding: 'utf8', mode: 0o666 });
|
|
}
|
|
catch (e) {
|
|
logfile = path_1.default.join(os_1.default.tmpdir(), `coc-nvim-${process.pid}.log`);
|
|
fs_1.default.writeFileSync(logfile, '', { encoding: 'utf8', mode: 0o666 });
|
|
// noop
|
|
}
|
|
}
|
|
log4js_1.default.configure({
|
|
disableClustering: true,
|
|
appenders: {
|
|
out: {
|
|
type: 'file',
|
|
mode: 0o666,
|
|
filename: logfile,
|
|
maxLogSize: MAX_LOG_SIZE,
|
|
backups: MAX_LOG_BACKUPS,
|
|
layout: {
|
|
type: 'pattern',
|
|
// Format log in following pattern:
|
|
// yyyy-MM-dd HH:mm:ss.mil $Level (pid:$pid) $categroy - $message.
|
|
pattern: `%d{ISO8601} %p (pid:${process.pid}) [%c] - %m`,
|
|
},
|
|
}
|
|
},
|
|
categories: {
|
|
default: { appenders: ['out'], level }
|
|
}
|
|
});
|
|
module.exports = (name = 'coc-nvim') => {
|
|
let logger = log4js_1.default.getLogger(name);
|
|
logger.getLogFile = () => {
|
|
return logfile;
|
|
};
|
|
return logger;
|
|
};
|
|
//# sourceMappingURL=logger.js.map
|
|
|
|
/***/ }),
|
|
/* 187 */
|
|
/***/ (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__(176));
|
|
const fs_1 = tslib_1.__importDefault(__webpack_require__(55));
|
|
const os_1 = tslib_1.__importDefault(__webpack_require__(56));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const util_1 = tslib_1.__importDefault(__webpack_require__(40));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const which_1 = tslib_1.__importDefault(__webpack_require__(181));
|
|
const configuration_1 = tslib_1.__importDefault(__webpack_require__(188));
|
|
const shape_1 = tslib_1.__importDefault(__webpack_require__(205));
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const db_1 = tslib_1.__importDefault(__webpack_require__(206));
|
|
const document_1 = tslib_1.__importDefault(__webpack_require__(207));
|
|
const fileSystemWatcher_1 = tslib_1.__importDefault(__webpack_require__(214));
|
|
const mru_1 = tslib_1.__importDefault(__webpack_require__(215));
|
|
const outputChannel_1 = tslib_1.__importDefault(__webpack_require__(216));
|
|
const resolver_1 = tslib_1.__importDefault(__webpack_require__(217));
|
|
const status_1 = tslib_1.__importDefault(__webpack_require__(219));
|
|
const task_1 = tslib_1.__importDefault(__webpack_require__(223));
|
|
const terminal_1 = tslib_1.__importDefault(__webpack_require__(224));
|
|
const willSaveHandler_1 = tslib_1.__importDefault(__webpack_require__(225));
|
|
const types_1 = __webpack_require__(189);
|
|
const array_1 = __webpack_require__(212);
|
|
const fs_2 = __webpack_require__(200);
|
|
const index_1 = __webpack_require__(174);
|
|
const match_1 = __webpack_require__(226);
|
|
const position_1 = __webpack_require__(213);
|
|
const string_1 = __webpack_require__(210);
|
|
const watchman_1 = tslib_1.__importDefault(__webpack_require__(227));
|
|
const uuid = __webpack_require__(220);
|
|
const requireFunc = true ? require : undefined;
|
|
const logger = __webpack_require__(186)('workspace');
|
|
const CONFIG_FILE_NAME = 'coc-settings.json';
|
|
let NAME_SPACE = 1080;
|
|
class Workspace {
|
|
constructor() {
|
|
this.keymaps = new Map();
|
|
this.resolver = new resolver_1.default();
|
|
this.rootPatterns = new Map();
|
|
this._workspaceFolders = [];
|
|
this._insertMode = false;
|
|
this._cwd = process.cwd();
|
|
this._blocking = false;
|
|
this._initialized = false;
|
|
this._attached = false;
|
|
this.buffers = new Map();
|
|
this.autocmdMaxId = 0;
|
|
this.autocmds = new Map();
|
|
this.terminals = new Map();
|
|
this.creatingSources = new Map();
|
|
this.outputChannels = new Map();
|
|
this.schemeProviderMap = new Map();
|
|
this.namespaceMap = new Map();
|
|
this.disposables = [];
|
|
this.watchedOptions = new Set();
|
|
this._disposed = false;
|
|
this._onDidOpenDocument = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidCloseDocument = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidChangeDocument = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onWillSaveDocument = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidSaveDocument = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidChangeWorkspaceFolders = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidChangeConfiguration = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidWorkspaceInitialized = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidOpenTerminal = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidCloseTerminal = new vscode_languageserver_protocol_1.Emitter();
|
|
this.onDidCloseTerminal = this._onDidCloseTerminal.event;
|
|
this.onDidOpenTerminal = this._onDidOpenTerminal.event;
|
|
this.onDidChangeWorkspaceFolders = this._onDidChangeWorkspaceFolders.event;
|
|
this.onDidOpenTextDocument = this._onDidOpenDocument.event;
|
|
this.onDidCloseTextDocument = this._onDidCloseDocument.event;
|
|
this.onDidChangeTextDocument = this._onDidChangeDocument.event;
|
|
this.onWillSaveTextDocument = this._onWillSaveDocument.event;
|
|
this.onDidSaveTextDocument = this._onDidSaveDocument.event;
|
|
this.onDidChangeConfiguration = this._onDidChangeConfiguration.event;
|
|
this.onDidWorkspaceInitialized = this._onDidWorkspaceInitialized.event;
|
|
let json = requireFunc('../package.json');
|
|
this.version = json.version;
|
|
this.configurations = this.createConfigurations();
|
|
this.willSaveUntilHandler = new willSaveHandler_1.default(this);
|
|
this.setupDynamicAutocmd = debounce_1.default(() => {
|
|
this._setupDynamicAutocmd().catch(e => {
|
|
logger.error(e);
|
|
});
|
|
}, global.hasOwnProperty('__TEST__') ? 0 : 100);
|
|
this.setMessageLevel();
|
|
}
|
|
async init() {
|
|
let { nvim } = this;
|
|
this.statusLine = new status_1.default(nvim);
|
|
this._env = await nvim.call('coc#util#vim_info');
|
|
this._insertMode = this._env.mode.startsWith('insert');
|
|
if (this._env.workspaceFolders) {
|
|
this._workspaceFolders = this._env.workspaceFolders.map(f => {
|
|
return {
|
|
uri: vscode_uri_1.URI.file(f).toString(),
|
|
name: path_1.default.dirname(f)
|
|
};
|
|
});
|
|
}
|
|
this.configurations.updateUserConfig(this._env.config);
|
|
events_1.default.on('InsertEnter', () => {
|
|
this._insertMode = true;
|
|
}, null, this.disposables);
|
|
events_1.default.on('InsertLeave', () => {
|
|
this._insertMode = false;
|
|
}, null, this.disposables);
|
|
events_1.default.on('BufEnter', this.onBufEnter, this, this.disposables);
|
|
events_1.default.on('CursorMoved', this.onCursorMoved, this, this.disposables);
|
|
events_1.default.on('DirChanged', this.onDirChanged, this, this.disposables);
|
|
events_1.default.on('BufCreate', this.onBufCreate, this, this.disposables);
|
|
events_1.default.on('BufUnload', this.onBufUnload, this, this.disposables);
|
|
events_1.default.on('TermOpen', this.onBufCreate, this, this.disposables);
|
|
events_1.default.on('TermClose', this.onBufUnload, this, this.disposables);
|
|
events_1.default.on('BufWritePost', this.onBufWritePost, this, this.disposables);
|
|
events_1.default.on('BufWritePre', this.onBufWritePre, this, this.disposables);
|
|
events_1.default.on('FileType', this.onFileTypeChange, this, this.disposables);
|
|
events_1.default.on('CursorHold', this.checkBuffer, this, this.disposables);
|
|
events_1.default.on('TextChanged', this.checkBuffer, this, this.disposables);
|
|
events_1.default.on('BufReadCmd', this.onBufReadCmd, this, this.disposables);
|
|
events_1.default.on('VimResized', (columns, lines) => {
|
|
Object.assign(this._env, { columns, lines });
|
|
}, null, this.disposables);
|
|
await this.attach();
|
|
this.attachChangedEvents();
|
|
this.configurations.onDidChange(e => {
|
|
this._onDidChangeConfiguration.fire(e);
|
|
}, null, this.disposables);
|
|
this.watchOption('runtimepath', (_, newValue) => {
|
|
this._env.runtimepath = newValue;
|
|
}, this.disposables);
|
|
this.watchOption('iskeyword', (_, newValue) => {
|
|
let doc = this.getDocument(this.bufnr);
|
|
if (doc)
|
|
doc.setIskeyword(newValue);
|
|
}, this.disposables);
|
|
this.watchOption('completeopt', async (_, newValue) => {
|
|
this.env.completeOpt = newValue;
|
|
if (!this._attached)
|
|
return;
|
|
if (this.insertMode) {
|
|
let suggest = this.getConfiguration('suggest');
|
|
if (suggest.get('autoTrigger') == 'always') {
|
|
console.error(`Some plugin change completeopt on insert mode!`); // tslint:disable-line
|
|
}
|
|
}
|
|
}, this.disposables);
|
|
this.watchGlobal('coc_enabled', async (oldValue, newValue) => {
|
|
if (newValue == oldValue)
|
|
return;
|
|
if (newValue == 1) {
|
|
await this.attach();
|
|
}
|
|
else {
|
|
await this.detach();
|
|
}
|
|
}, this.disposables);
|
|
let provider = {
|
|
onDidChange: null,
|
|
provideTextDocumentContent: async (uri) => {
|
|
let channel = this.outputChannels.get(uri.path.slice(1));
|
|
if (!channel)
|
|
return '';
|
|
nvim.pauseNotification();
|
|
nvim.command('setlocal nospell nofoldenable wrap noswapfile', true);
|
|
nvim.command('setlocal buftype=nofile bufhidden=hide', true);
|
|
nvim.command('setfiletype log', true);
|
|
await nvim.resumeNotification();
|
|
return channel.content;
|
|
}
|
|
};
|
|
this.disposables.push(this.registerTextDocumentContentProvider('output', provider));
|
|
}
|
|
getConfigFile(target) {
|
|
return this.configurations.getConfigFile(target);
|
|
}
|
|
/**
|
|
* Register autocmd on vim.
|
|
*/
|
|
registerAutocmd(autocmd) {
|
|
this.autocmdMaxId += 1;
|
|
let id = this.autocmdMaxId;
|
|
this.autocmds.set(id, autocmd);
|
|
this.setupDynamicAutocmd();
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.autocmds.delete(id);
|
|
this.setupDynamicAutocmd();
|
|
});
|
|
}
|
|
/**
|
|
* Watch for option change.
|
|
*/
|
|
watchOption(key, callback, disposables) {
|
|
let watching = this.watchedOptions.has(key);
|
|
if (!watching) {
|
|
this.watchedOptions.add(key);
|
|
this.setupDynamicAutocmd();
|
|
}
|
|
let disposable = events_1.default.on('OptionSet', async (changed, oldValue, newValue) => {
|
|
if (changed == key && callback) {
|
|
await Promise.resolve(callback(oldValue, newValue));
|
|
}
|
|
});
|
|
if (disposables) {
|
|
disposables.push(vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
disposable.dispose();
|
|
if (watching)
|
|
return;
|
|
this.watchedOptions.delete(key);
|
|
this.setupDynamicAutocmd();
|
|
}));
|
|
}
|
|
}
|
|
/**
|
|
* Watch global variable, works on neovim only.
|
|
*/
|
|
watchGlobal(key, callback, disposables) {
|
|
let { nvim } = this;
|
|
nvim.call('coc#_watch', key, true);
|
|
let disposable = events_1.default.on('GlobalChange', async (changed, oldValue, newValue) => {
|
|
if (changed == key && callback) {
|
|
await Promise.resolve(callback(oldValue, newValue));
|
|
}
|
|
});
|
|
if (disposables) {
|
|
disposables.push(vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
disposable.dispose();
|
|
nvim.call('coc#_unwatch', key, true);
|
|
}));
|
|
}
|
|
}
|
|
get cwd() {
|
|
return this._cwd;
|
|
}
|
|
get env() {
|
|
return this._env;
|
|
}
|
|
get root() {
|
|
return this._root || this.cwd;
|
|
}
|
|
get rootPath() {
|
|
return this.root;
|
|
}
|
|
get workspaceFolders() {
|
|
return this._workspaceFolders;
|
|
}
|
|
/**
|
|
* uri of current file, could be null
|
|
*/
|
|
get uri() {
|
|
let { bufnr } = this;
|
|
if (bufnr) {
|
|
let document = this.getDocument(bufnr);
|
|
if (document && document.schema == 'file') {
|
|
return document.uri;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
get workspaceFolder() {
|
|
let { rootPath } = this;
|
|
if (rootPath == os_1.default.homedir())
|
|
return null;
|
|
return {
|
|
uri: vscode_uri_1.URI.file(rootPath).toString(),
|
|
name: path_1.default.basename(rootPath)
|
|
};
|
|
}
|
|
get textDocuments() {
|
|
let docs = [];
|
|
for (let b of this.buffers.values()) {
|
|
docs.push(b.textDocument);
|
|
}
|
|
return docs;
|
|
}
|
|
get documents() {
|
|
return Array.from(this.buffers.values());
|
|
}
|
|
createNameSpace(name = '') {
|
|
if (this.namespaceMap.has(name))
|
|
return this.namespaceMap.get(name);
|
|
NAME_SPACE = NAME_SPACE + 1;
|
|
this.namespaceMap.set(name, NAME_SPACE);
|
|
return NAME_SPACE;
|
|
}
|
|
get channelNames() {
|
|
return Array.from(this.outputChannels.keys());
|
|
}
|
|
get pluginRoot() {
|
|
return path_1.default.dirname(__dirname);
|
|
}
|
|
get isVim() {
|
|
return this._env.isVim;
|
|
}
|
|
get isNvim() {
|
|
return !this._env.isVim;
|
|
}
|
|
get completeOpt() {
|
|
return this._env.completeOpt;
|
|
}
|
|
get initialized() {
|
|
return this._initialized;
|
|
}
|
|
get ready() {
|
|
if (this._initialized)
|
|
return Promise.resolve();
|
|
return new Promise(resolve => {
|
|
let disposable = this.onDidWorkspaceInitialized(() => {
|
|
disposable.dispose();
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
/**
|
|
* Current filetypes.
|
|
*/
|
|
get filetypes() {
|
|
let res = new Set();
|
|
for (let doc of this.documents) {
|
|
res.add(doc.filetype);
|
|
}
|
|
return res;
|
|
}
|
|
/**
|
|
* Check if selector match document.
|
|
*/
|
|
match(selector, document) {
|
|
return match_1.score(selector, document.uri, document.languageId);
|
|
}
|
|
/**
|
|
* Findup for filename or filenames from current filepath or root.
|
|
*/
|
|
async findUp(filename) {
|
|
let { cwd } = this;
|
|
let filepath = await this.nvim.call('expand', '%:p');
|
|
filepath = path_1.default.normalize(filepath);
|
|
let isFile = filepath && path_1.default.isAbsolute(filepath);
|
|
if (isFile && !fs_2.isParentFolder(cwd, filepath)) {
|
|
// can't use cwd
|
|
return fs_2.findUp(filename, path_1.default.dirname(filepath));
|
|
}
|
|
let res = fs_2.findUp(filename, cwd);
|
|
if (res && res != os_1.default.homedir())
|
|
return res;
|
|
if (isFile)
|
|
return fs_2.findUp(filename, path_1.default.dirname(filepath));
|
|
return null;
|
|
}
|
|
async resolveRootFolder(uri, patterns) {
|
|
let { cwd } = this;
|
|
if (uri.scheme != 'file')
|
|
return cwd;
|
|
let filepath = path_1.default.normalize(uri.fsPath);
|
|
let dir = path_1.default.dirname(filepath);
|
|
return fs_2.resolveRoot(dir, patterns) || dir;
|
|
}
|
|
/**
|
|
* Create a FileSystemWatcher instance,
|
|
* doesn't fail when watchman not found.
|
|
*/
|
|
createFileSystemWatcher(globPattern, ignoreCreate, ignoreChange, ignoreDelete) {
|
|
let watchmanPath = false ? undefined : this.getWatchmanPath();
|
|
let channel = watchmanPath ? this.createOutputChannel('watchman') : null;
|
|
let promise = watchmanPath ? watchman_1.default.createClient(watchmanPath, this.root, channel) : Promise.resolve(null);
|
|
let watcher = new fileSystemWatcher_1.default(promise, globPattern, !!ignoreCreate, !!ignoreChange, !!ignoreDelete);
|
|
return watcher;
|
|
}
|
|
getWatchmanPath() {
|
|
const preferences = this.getConfiguration('coc.preferences');
|
|
let watchmanPath = preferences.get('watchmanPath', 'watchman');
|
|
try {
|
|
return which_1.default.sync(watchmanPath);
|
|
}
|
|
catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
/**
|
|
* Get configuration by section and optional resource uri.
|
|
*/
|
|
getConfiguration(section, resource) {
|
|
return this.configurations.getConfiguration(section, resource);
|
|
}
|
|
/**
|
|
* Get created document by uri or bufnr.
|
|
*/
|
|
getDocument(uri) {
|
|
if (typeof uri === 'number') {
|
|
return this.buffers.get(uri);
|
|
}
|
|
uri = vscode_uri_1.URI.parse(uri).toString();
|
|
for (let doc of this.buffers.values()) {
|
|
if (doc && doc.uri === uri)
|
|
return doc;
|
|
}
|
|
return null;
|
|
}
|
|
/**
|
|
* Get current cursor offset in document.
|
|
*/
|
|
async getOffset() {
|
|
let document = await this.document;
|
|
let pos = await this.getCursorPosition();
|
|
return document.textDocument.offsetAt(pos);
|
|
}
|
|
/**
|
|
* Apply WorkspaceEdit.
|
|
*/
|
|
async applyEdit(edit) {
|
|
let { nvim } = this;
|
|
let { documentChanges, changes } = edit;
|
|
if (documentChanges) {
|
|
documentChanges = this.mergeDocumentChanges(documentChanges);
|
|
if (!this.validteDocumentChanges(documentChanges))
|
|
return false;
|
|
}
|
|
let [bufnr, cursor] = await nvim.eval('[bufnr("%"),coc#util#cursor()]');
|
|
let document = this.getDocument(bufnr);
|
|
let uri = document ? document.uri : null;
|
|
let currEdits = null;
|
|
try {
|
|
if (documentChanges && documentChanges.length) {
|
|
let n = documentChanges.length;
|
|
for (let change of documentChanges) {
|
|
if (index_1.isDocumentEdit(change)) {
|
|
let { textDocument, edits } = change;
|
|
if (vscode_uri_1.URI.parse(textDocument.uri).toString() == uri)
|
|
currEdits = edits;
|
|
let doc = await this.loadFile(textDocument.uri);
|
|
await doc.applyEdits(nvim, edits);
|
|
}
|
|
else if (vscode_languageserver_protocol_1.CreateFile.is(change)) {
|
|
let file = vscode_uri_1.URI.parse(change.uri).fsPath;
|
|
await this.createFile(file, change.options);
|
|
}
|
|
else if (vscode_languageserver_protocol_1.RenameFile.is(change)) {
|
|
await this.renameFile(vscode_uri_1.URI.parse(change.oldUri).fsPath, vscode_uri_1.URI.parse(change.newUri).fsPath, change.options);
|
|
}
|
|
else if (vscode_languageserver_protocol_1.DeleteFile.is(change)) {
|
|
await this.deleteFile(vscode_uri_1.URI.parse(change.uri).fsPath, change.options);
|
|
}
|
|
}
|
|
this.showMessage(`${n} buffers changed.`);
|
|
}
|
|
else if (changes) {
|
|
await this.loadFiles(Object.keys(changes));
|
|
for (let uri of Object.keys(changes)) {
|
|
let document = await this.loadFile(uri);
|
|
if (vscode_uri_1.URI.parse(uri).toString() == uri)
|
|
currEdits = changes[uri];
|
|
await document.applyEdits(nvim, changes[uri]);
|
|
}
|
|
this.showMessage(`${Object.keys(changes).length} buffers changed.`);
|
|
}
|
|
if (currEdits) {
|
|
let changed = position_1.getChangedFromEdits({ line: cursor[0], character: cursor[1] }, currEdits);
|
|
if (changed)
|
|
await this.moveTo({
|
|
line: cursor[0] + changed.line,
|
|
character: cursor[1] + changed.character
|
|
});
|
|
}
|
|
}
|
|
catch (e) {
|
|
logger.error(e);
|
|
this.showMessage(`Error on applyEdits: ${e}`, 'error');
|
|
return false;
|
|
}
|
|
await index_1.wait(50);
|
|
return true;
|
|
}
|
|
/**
|
|
* Convert location to quickfix item.
|
|
*/
|
|
async getQuickfixItem(loc, text, type = '', module) {
|
|
if (vscode_languageserver_protocol_1.LocationLink.is(loc)) {
|
|
loc = vscode_languageserver_protocol_1.Location.create(loc.targetUri, loc.targetRange);
|
|
}
|
|
let doc = this.getDocument(loc.uri);
|
|
let { uri, range } = loc;
|
|
let { line, character } = range.start;
|
|
let u = vscode_uri_1.URI.parse(uri);
|
|
let bufnr = doc ? doc.bufnr : -1;
|
|
if (!text && u.scheme == 'file') {
|
|
text = await this.getLine(uri, line);
|
|
character = string_1.byteIndex(text, character);
|
|
}
|
|
let item = {
|
|
uri,
|
|
filename: u.scheme == 'file' ? u.fsPath : uri,
|
|
lnum: line + 1,
|
|
col: character + 1,
|
|
text: text || '',
|
|
range
|
|
};
|
|
if (module)
|
|
item.module = module;
|
|
if (type)
|
|
item.type = type;
|
|
if (bufnr != -1)
|
|
item.bufnr = bufnr;
|
|
return item;
|
|
}
|
|
/**
|
|
* Create persistence Mru instance.
|
|
*/
|
|
createMru(name) {
|
|
return new mru_1.default(name);
|
|
}
|
|
async getSelectedRange(mode, document) {
|
|
let { nvim } = this;
|
|
if (['v', 'V', 'char', 'line', '\x16'].indexOf(mode) == -1) {
|
|
this.showMessage(`Mode '${mode}' is not supported`, 'error');
|
|
return null;
|
|
}
|
|
let isVisual = ['v', 'V', '\x16'].indexOf(mode) != -1;
|
|
let [, sl, sc] = await nvim.call('getpos', isVisual ? `'<` : `'[`);
|
|
let [, el, ec] = await nvim.call('getpos', isVisual ? `'>` : `']`);
|
|
let range = vscode_languageserver_protocol_1.Range.create(document.getPosition(sl, sc), document.getPosition(el, ec));
|
|
if (mode == 'v' || mode == '\x16') {
|
|
range.end.character = range.end.character + 1;
|
|
}
|
|
return range;
|
|
}
|
|
/**
|
|
* Visual select range of current document
|
|
*/
|
|
async selectRange(range) {
|
|
let { nvim } = this;
|
|
let { start, end } = range;
|
|
let [bufnr, ve, selection] = await nvim.eval(`[bufnr('%'), &virtualedit, &selection, mode()]`);
|
|
let document = this.getDocument(bufnr);
|
|
if (!document)
|
|
return;
|
|
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;
|
|
let move_cmd = '';
|
|
let resetVirtualEdit = false;
|
|
move_cmd += 'v';
|
|
endCol = await nvim.eval(`virtcol([${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 nvim.eval(`virtcol([${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)
|
|
nvim.command(`normal! ${move_cmd}`, true);
|
|
if (resetVirtualEdit)
|
|
nvim.setOption('virtualedit', ve, true);
|
|
if (this.isVim)
|
|
nvim.command('redraw', true);
|
|
await nvim.resumeNotification();
|
|
}
|
|
/**
|
|
* Populate locations to UI.
|
|
*/
|
|
async showLocations(locations) {
|
|
let items = await Promise.all(locations.map(loc => {
|
|
return this.getQuickfixItem(loc);
|
|
}));
|
|
let { nvim } = this;
|
|
const preferences = this.getConfiguration('coc.preferences');
|
|
if (preferences.get('useQuickfixForLocations', false)) {
|
|
await nvim.call('setqflist', [items]);
|
|
nvim.command('copen', true);
|
|
}
|
|
else {
|
|
await nvim.setVar('coc_jump_locations', items);
|
|
if (this.env.locationlist) {
|
|
nvim.command('CocList --normal --auto-preview location', true);
|
|
}
|
|
else {
|
|
nvim.command('doautocmd User CocLocationsChange', true);
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Get content of line by uri and line.
|
|
*/
|
|
async getLine(uri, line) {
|
|
let document = this.getDocument(uri);
|
|
if (document)
|
|
return document.getline(line) || '';
|
|
if (!uri.startsWith('file:'))
|
|
return '';
|
|
return await fs_2.readFileLine(vscode_uri_1.URI.parse(uri).fsPath, line);
|
|
}
|
|
/**
|
|
* Get WorkspaceFolder of uri
|
|
*/
|
|
getWorkspaceFolder(uri) {
|
|
this.workspaceFolders.sort((a, b) => b.uri.length - a.uri.length);
|
|
let filepath = vscode_uri_1.URI.parse(uri).fsPath;
|
|
return this.workspaceFolders.find(folder => fs_2.isParentFolder(vscode_uri_1.URI.parse(folder.uri).fsPath, filepath));
|
|
}
|
|
/**
|
|
* Get content from buffer of file by uri.
|
|
*/
|
|
async readFile(uri) {
|
|
let document = this.getDocument(uri);
|
|
if (document) {
|
|
document.forceSync();
|
|
return document.content;
|
|
}
|
|
let u = vscode_uri_1.URI.parse(uri);
|
|
if (u.scheme != 'file')
|
|
return '';
|
|
let encoding = await this.getFileEncoding();
|
|
return await fs_2.readFile(u.fsPath, encoding);
|
|
}
|
|
getFilepath(filepath) {
|
|
let { cwd } = this;
|
|
let rel = path_1.default.relative(cwd, filepath);
|
|
return rel.startsWith('..') ? filepath : rel;
|
|
}
|
|
onWillSaveUntil(callback, thisArg, clientId) {
|
|
return this.willSaveUntilHandler.addCallback(callback, thisArg, clientId);
|
|
}
|
|
/**
|
|
* Echo lines.
|
|
*/
|
|
async echoLines(lines, truncate = false) {
|
|
let { nvim } = this;
|
|
let cmdHeight = this.env.cmdheight;
|
|
if (lines.length > cmdHeight && truncate) {
|
|
lines = lines.slice(0, cmdHeight);
|
|
}
|
|
let maxLen = this.env.columns - 12;
|
|
lines = lines.map(line => {
|
|
line = line.replace(/\n/g, ' ');
|
|
if (truncate)
|
|
line = line.slice(0, maxLen);
|
|
return line;
|
|
});
|
|
if (truncate && lines.length == cmdHeight) {
|
|
let last = lines[lines.length - 1];
|
|
lines[cmdHeight - 1] = `${last.length == maxLen ? last.slice(0, -4) : last} ...`;
|
|
}
|
|
nvim.callTimer('coc#util#echo_lines', [lines], true);
|
|
}
|
|
/**
|
|
* Show message in vim.
|
|
*/
|
|
showMessage(msg, identify = 'more') {
|
|
if (this._blocking || !this.nvim)
|
|
return;
|
|
let { messageLevel } = this;
|
|
let level = types_1.MessageLevel.Error;
|
|
let method = index_1.echoErr;
|
|
switch (identify) {
|
|
case 'more':
|
|
level = types_1.MessageLevel.More;
|
|
method = index_1.echoMessage;
|
|
break;
|
|
case 'warning':
|
|
level = types_1.MessageLevel.Warning;
|
|
method = index_1.echoWarning;
|
|
break;
|
|
}
|
|
if (level >= messageLevel) {
|
|
method(this.nvim, msg);
|
|
}
|
|
}
|
|
/**
|
|
* Current document.
|
|
*/
|
|
get document() {
|
|
let { bufnr } = this;
|
|
if (bufnr == null)
|
|
return null;
|
|
if (this.buffers.has(bufnr)) {
|
|
return Promise.resolve(this.buffers.get(bufnr));
|
|
}
|
|
if (!this.creatingSources.has(bufnr)) {
|
|
this.onBufCreate(bufnr).logError();
|
|
}
|
|
return new Promise(resolve => {
|
|
let disposable = this.onDidOpenTextDocument(doc => {
|
|
disposable.dispose();
|
|
resolve(this.getDocument(doc.uri));
|
|
});
|
|
});
|
|
}
|
|
/**
|
|
* Get current cursor position.
|
|
*/
|
|
async getCursorPosition() {
|
|
let [line, character] = await this.nvim.call('coc#util#cursor');
|
|
return vscode_languageserver_protocol_1.Position.create(line, character);
|
|
}
|
|
/**
|
|
* Get current document and position.
|
|
*/
|
|
async getCurrentState() {
|
|
let document = await this.document;
|
|
let position = await this.getCursorPosition();
|
|
return {
|
|
document: document.textDocument,
|
|
position
|
|
};
|
|
}
|
|
/**
|
|
* Get format options
|
|
*/
|
|
async getFormatOptions(uri) {
|
|
let doc;
|
|
if (uri) {
|
|
doc = this.getDocument(uri);
|
|
}
|
|
else {
|
|
doc = this.getDocument(this.bufnr);
|
|
}
|
|
let tabSize = await this.getDocumentOption('shiftwidth', doc);
|
|
if (!tabSize)
|
|
tabSize = await this.getDocumentOption('tabstop', doc);
|
|
let insertSpaces = (await this.getDocumentOption('expandtab', doc)) == 1;
|
|
return {
|
|
tabSize,
|
|
insertSpaces
|
|
};
|
|
}
|
|
/**
|
|
* Jump to location.
|
|
*/
|
|
async jumpTo(uri, position, openCommand) {
|
|
const preferences = this.getConfiguration('coc.preferences');
|
|
let jumpCommand = openCommand || preferences.get('jumpCommand', 'edit');
|
|
let { nvim } = this;
|
|
let doc = this.getDocument(uri);
|
|
let bufnr = doc ? doc.bufnr : -1;
|
|
await nvim.command(`normal! m'`);
|
|
if (bufnr == this.bufnr && jumpCommand == 'edit') {
|
|
if (position)
|
|
await this.moveTo(position);
|
|
}
|
|
else if (bufnr != -1 && jumpCommand == 'edit') {
|
|
let moveCmd = '';
|
|
if (position) {
|
|
let line = doc.getline(position.line);
|
|
let col = string_1.byteLength(line.slice(0, position.character)) + 1;
|
|
moveCmd = position ? `+call\\ cursor(${position.line + 1},${col})` : '';
|
|
}
|
|
await this.nvim.call('coc#util#execute', [`buffer ${moveCmd} ${bufnr}`]);
|
|
}
|
|
else {
|
|
let { fsPath, scheme } = vscode_uri_1.URI.parse(uri);
|
|
let pos = position == null ? null : [position.line + 1, position.character + 1];
|
|
if (scheme == 'file') {
|
|
let bufname = fs_2.fixDriver(path_1.default.normalize(fsPath));
|
|
await this.nvim.call('coc#util#jump', [jumpCommand, bufname, pos]);
|
|
}
|
|
else {
|
|
await this.nvim.call('coc#util#jump', [jumpCommand, uri, pos]);
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Move cursor to position.
|
|
*/
|
|
async moveTo(position) {
|
|
await this.nvim.call('coc#util#jumpTo', [position.line, position.character]);
|
|
}
|
|
/**
|
|
* Create a file in vim and disk
|
|
*/
|
|
async createFile(filepath, opts = {}) {
|
|
let stat = await fs_2.statAsync(filepath);
|
|
if (stat && !opts.overwrite && !opts.ignoreIfExists) {
|
|
this.showMessage(`${filepath} already exists!`, 'error');
|
|
return;
|
|
}
|
|
if (!stat || opts.overwrite) {
|
|
// directory
|
|
if (filepath.endsWith('/')) {
|
|
try {
|
|
if (filepath.startsWith('~'))
|
|
filepath = filepath.replace(/^~/, os_1.default.homedir());
|
|
await index_1.mkdirp(filepath);
|
|
}
|
|
catch (e) {
|
|
this.showMessage(`Can't create ${filepath}: ${e.message}`, 'error');
|
|
}
|
|
}
|
|
else {
|
|
let uri = vscode_uri_1.URI.file(filepath).toString();
|
|
let doc = this.getDocument(uri);
|
|
if (doc)
|
|
return;
|
|
let encoding = await this.getFileEncoding();
|
|
fs_1.default.writeFileSync(filepath, '', encoding || '');
|
|
await this.loadFile(uri);
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Load uri as document.
|
|
*/
|
|
async loadFile(uri) {
|
|
let doc = this.getDocument(uri);
|
|
if (doc)
|
|
return doc;
|
|
let { nvim } = this;
|
|
let filepath = uri.startsWith('file') ? vscode_uri_1.URI.parse(uri).fsPath : uri;
|
|
nvim.call('coc#util#open_files', [[filepath]], true);
|
|
return await new Promise((resolve, reject) => {
|
|
let disposable = this.onDidOpenTextDocument(textDocument => {
|
|
let fsPath = vscode_uri_1.URI.parse(textDocument.uri).fsPath;
|
|
if (textDocument.uri == uri || fsPath == filepath) {
|
|
clearTimeout(timer);
|
|
disposable.dispose();
|
|
resolve(this.getDocument(uri));
|
|
}
|
|
});
|
|
let timer = setTimeout(() => {
|
|
disposable.dispose();
|
|
reject(new Error(`Create document ${uri} timeout after 1s.`));
|
|
}, 1000);
|
|
});
|
|
}
|
|
/**
|
|
* Load the files that not loaded
|
|
*/
|
|
async loadFiles(uris) {
|
|
uris = uris.filter(uri => this.getDocument(uri) == null);
|
|
if (!uris.length)
|
|
return;
|
|
let bufnrs = await this.nvim.call('coc#util#open_files', [uris.map(u => vscode_uri_1.URI.parse(u).fsPath)]);
|
|
let create = bufnrs.filter(bufnr => this.getDocument(bufnr) == null);
|
|
if (!create.length)
|
|
return;
|
|
create.map(bufnr => this.onBufCreate(bufnr).logError());
|
|
return new Promise((resolve, reject) => {
|
|
let timer = setTimeout(() => {
|
|
disposable.dispose();
|
|
reject(new Error(`Create document timeout after 2s.`));
|
|
}, 2000);
|
|
let disposable = this.onDidOpenTextDocument(() => {
|
|
if (uris.every(uri => this.getDocument(uri) != null)) {
|
|
clearTimeout(timer);
|
|
disposable.dispose();
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
/**
|
|
* Rename file in vim and disk
|
|
*/
|
|
async renameFile(oldPath, newPath, opts = {}) {
|
|
let { overwrite, ignoreIfExists } = opts;
|
|
let stat = await fs_2.statAsync(newPath);
|
|
if (stat && !overwrite && !ignoreIfExists) {
|
|
this.showMessage(`${newPath} already exists`, 'error');
|
|
return;
|
|
}
|
|
if (!stat || overwrite) {
|
|
try {
|
|
await fs_2.renameAsync(oldPath, newPath);
|
|
let uri = vscode_uri_1.URI.file(oldPath).toString();
|
|
let doc = this.getDocument(uri);
|
|
if (doc) {
|
|
await doc.buffer.setName(newPath);
|
|
// avoid cancel by unload
|
|
await this.onBufCreate(doc.bufnr);
|
|
}
|
|
}
|
|
catch (e) {
|
|
this.showMessage(`Rename error ${e.message}`, 'error');
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Delete file from vim and disk.
|
|
*/
|
|
async deleteFile(filepath, opts = {}) {
|
|
let { ignoreIfNotExists, recursive } = opts;
|
|
let stat = await fs_2.statAsync(filepath.replace(/\/$/, ''));
|
|
let isDir = stat && stat.isDirectory() || filepath.endsWith('/');
|
|
if (!stat && !ignoreIfNotExists) {
|
|
this.showMessage(`${filepath} not exists`, 'error');
|
|
return;
|
|
}
|
|
if (stat == null)
|
|
return;
|
|
if (isDir && !recursive) {
|
|
this.showMessage(`Can't remove directory, recursive not set`, 'error');
|
|
return;
|
|
}
|
|
try {
|
|
let method = isDir ? 'rmdir' : 'unlink';
|
|
await util_1.default.promisify(fs_1.default[method])(filepath);
|
|
if (!isDir) {
|
|
let uri = vscode_uri_1.URI.file(filepath).toString();
|
|
let doc = this.getDocument(uri);
|
|
if (doc)
|
|
await this.nvim.command(`silent bwipeout ${doc.bufnr}`);
|
|
}
|
|
}
|
|
catch (e) {
|
|
this.showMessage(`Error on delete ${filepath}: ${e.message}`, 'error');
|
|
}
|
|
}
|
|
/**
|
|
* Open resource by uri
|
|
*/
|
|
async openResource(uri) {
|
|
let { nvim } = this;
|
|
// not supported
|
|
if (uri.startsWith('http')) {
|
|
await nvim.call('coc#util#open_url', uri);
|
|
return;
|
|
}
|
|
let wildignore = await nvim.getOption('wildignore');
|
|
await nvim.setOption('wildignore', '');
|
|
await this.jumpTo(uri);
|
|
await nvim.setOption('wildignore', wildignore);
|
|
}
|
|
/**
|
|
* Create a new output channel
|
|
*/
|
|
createOutputChannel(name) {
|
|
if (this.outputChannels.has(name))
|
|
return this.outputChannels.get(name);
|
|
let channel = new outputChannel_1.default(name, this.nvim);
|
|
this.outputChannels.set(name, channel);
|
|
return channel;
|
|
}
|
|
/**
|
|
* Reveal buffer of output channel.
|
|
*/
|
|
showOutputChannel(name, preserveFocus) {
|
|
let channel = this.outputChannels.get(name);
|
|
if (!channel) {
|
|
this.showMessage(`Channel "${name}" not found`, 'error');
|
|
return;
|
|
}
|
|
channel.show(preserveFocus);
|
|
}
|
|
/**
|
|
* Resovle module from yarn or npm.
|
|
*/
|
|
async resolveModule(name) {
|
|
return await this.resolver.resolveModule(name);
|
|
}
|
|
/**
|
|
* Run nodejs command
|
|
*/
|
|
async runCommand(cmd, cwd, timeout) {
|
|
cwd = cwd || this.cwd;
|
|
return index_1.runCommand(cmd, { cwd }, timeout);
|
|
}
|
|
/**
|
|
* Run command in vim terminal
|
|
*/
|
|
async runTerminalCommand(cmd, cwd = this.cwd, keepfocus = false) {
|
|
return await this.nvim.callAsync('coc#util#run_terminal', { cmd, cwd, keepfocus: keepfocus ? 1 : 0 });
|
|
}
|
|
async createTerminal(opts) {
|
|
let cmd = opts.shellPath;
|
|
let args = opts.shellArgs;
|
|
if (!cmd)
|
|
cmd = await this.nvim.getOption('shell');
|
|
let terminal = new terminal_1.default(cmd, args || [], this.nvim, opts.name);
|
|
await terminal.start(opts.cwd || this.cwd, opts.env);
|
|
this.terminals.set(terminal.bufnr, terminal);
|
|
this._onDidOpenTerminal.fire(terminal);
|
|
return terminal;
|
|
}
|
|
/**
|
|
* Show quickpick
|
|
*/
|
|
async showQuickpick(items, placeholder = 'Choose by number') {
|
|
let msgs = [placeholder + ':'];
|
|
msgs = msgs.concat(items.map((str, index) => {
|
|
return `${index + 1}. ${str}`;
|
|
}));
|
|
let res = await this.callAsync('inputlist', [msgs]);
|
|
let n = parseInt(res, 10);
|
|
if (isNaN(n) || n <= 0 || n > msgs.length)
|
|
return -1;
|
|
return n - 1;
|
|
}
|
|
/**
|
|
* Prompt for confirm action.
|
|
*/
|
|
async showPrompt(title) {
|
|
this._blocking = true;
|
|
let res = await this.nvim.callAsync('coc#util#with_callback', ['coc#util#prompt_confirm', [title]]);
|
|
this._blocking = false;
|
|
return res == 1;
|
|
}
|
|
async callAsync(method, args) {
|
|
if (this.isNvim)
|
|
return await this.nvim.call(method, args);
|
|
return await this.nvim.callAsync('coc#util#with_callback', [method, args]);
|
|
}
|
|
/**
|
|
* Request input from user
|
|
*/
|
|
async requestInput(title, defaultValue) {
|
|
let { nvim } = this;
|
|
let res = await this.callAsync('input', [title + ': ', defaultValue || '']);
|
|
nvim.command('normal! :<C-u>', true);
|
|
if (!res) {
|
|
this.showMessage('Empty word, canceled', 'warning');
|
|
return null;
|
|
}
|
|
return res;
|
|
}
|
|
/**
|
|
* registerTextDocumentContentProvider
|
|
*/
|
|
registerTextDocumentContentProvider(scheme, provider) {
|
|
this.schemeProviderMap.set(scheme, provider);
|
|
this.setupDynamicAutocmd(); // tslint:disable-line
|
|
let disposables = [];
|
|
if (provider.onDidChange) {
|
|
provider.onDidChange(async (uri) => {
|
|
let doc = this.getDocument(uri.toString());
|
|
if (doc) {
|
|
let { buffer } = doc;
|
|
let tokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource();
|
|
let content = await Promise.resolve(provider.provideTextDocumentContent(uri, tokenSource.token));
|
|
await buffer.setLines(content.split('\n'), {
|
|
start: 0,
|
|
end: -1,
|
|
strictIndexing: false
|
|
});
|
|
}
|
|
}, null, disposables);
|
|
}
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.schemeProviderMap.delete(scheme);
|
|
index_1.disposeAll(disposables);
|
|
this.setupDynamicAutocmd();
|
|
});
|
|
}
|
|
/**
|
|
* Register keymap
|
|
*/
|
|
registerKeymap(modes, key, fn, opts = {}) {
|
|
if (this.keymaps.has(key))
|
|
return;
|
|
opts = Object.assign({ sync: true, cancel: true, silent: true, repeat: false }, opts);
|
|
let { nvim } = this;
|
|
this.keymaps.set(key, [fn, !!opts.repeat]);
|
|
let method = opts.sync ? 'request' : 'notify';
|
|
let silent = opts.silent ? '<silent>' : '';
|
|
for (let m of modes) {
|
|
if (m == 'i') {
|
|
nvim.command(`inoremap ${silent}<expr> <Plug>(coc-${key}) coc#_insert_key('${method}', '${key}', ${opts.cancel ? 1 : 0})`, true);
|
|
}
|
|
else {
|
|
let modify = index_1.getKeymapModifier(m);
|
|
nvim.command(`${m}noremap ${silent} <Plug>(coc-${key}) :${modify}call coc#rpc#${method}('doKeymap', ['${key}'])<cr>`, true);
|
|
}
|
|
}
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.keymaps.delete(key);
|
|
for (let m of modes) {
|
|
nvim.command(`${m}unmap <Plug>(coc-${key})`, true);
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* Register expr keymap.
|
|
*/
|
|
registerExprKeymap(mode, key, fn, buffer = false) {
|
|
let id = uuid();
|
|
let { nvim } = this;
|
|
this.keymaps.set(id, [fn, false]);
|
|
if (mode == 'i') {
|
|
nvim.command(`inoremap <silent><expr>${buffer ? '<nowait><buffer>' : ''} ${key} coc#_insert_key('request', '${id}')`, true);
|
|
}
|
|
else {
|
|
nvim.command(`${mode}noremap <silent><expr>${buffer ? '<nowait><buffer>' : ''} ${key} coc#rpc#request('doKeymap', ['${id}'])`, true);
|
|
}
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.keymaps.delete(id);
|
|
nvim.command(`${mode}unmap ${buffer ? '<buffer>' : ''} ${key}`, true);
|
|
});
|
|
}
|
|
registerLocalKeymap(mode, key, fn, notify = false) {
|
|
let id = uuid();
|
|
let { nvim } = this;
|
|
this.keymaps.set(id, [fn, false]);
|
|
nvim.command(`${mode}noremap <silent><nowait><buffer> ${key} :<c-u>call coc#rpc#${notify ? 'notify' : 'request'}('doKeymap', ['${id}'])<CR>`, true);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.keymaps.delete(id);
|
|
nvim.command(`${mode}unmap <buffer> ${key}`, true);
|
|
});
|
|
}
|
|
/**
|
|
* Create StatusBarItem
|
|
*/
|
|
createStatusBarItem(priority = 0, opt = {}) {
|
|
if (!this.statusLine) {
|
|
// tslint:disable-next-line: no-empty
|
|
let fn = () => { };
|
|
return { text: '', show: fn, dispose: fn, hide: fn, priority: 0, isProgress: true };
|
|
}
|
|
return this.statusLine.createStatusBarItem(priority, opt.progress || false);
|
|
}
|
|
dispose() {
|
|
this._disposed = true;
|
|
for (let ch of this.outputChannels.values()) {
|
|
ch.dispose();
|
|
}
|
|
for (let doc of this.documents) {
|
|
doc.detach();
|
|
}
|
|
index_1.disposeAll(this.disposables);
|
|
watchman_1.default.dispose();
|
|
this.configurations.dispose();
|
|
this.setupDynamicAutocmd.clear();
|
|
this.buffers.clear();
|
|
if (this.statusLine)
|
|
this.statusLine.dispose();
|
|
}
|
|
async detach() {
|
|
if (!this._attached)
|
|
return;
|
|
this._attached = false;
|
|
for (let bufnr of this.buffers.keys()) {
|
|
await events_1.default.fire('BufUnload', [bufnr]);
|
|
}
|
|
}
|
|
/**
|
|
* Create DB instance at extension root.
|
|
*/
|
|
createDatabase(name) {
|
|
let root;
|
|
if (global.hasOwnProperty('__TEST__')) {
|
|
root = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'coc-'));
|
|
}
|
|
else {
|
|
root = path_1.default.dirname(this.env.extensionRoot);
|
|
}
|
|
let filepath = path_1.default.join(root, name + '.json');
|
|
return new db_1.default(filepath);
|
|
}
|
|
/**
|
|
* Create Task instance that runs in vim.
|
|
*/
|
|
createTask(id) {
|
|
return new task_1.default(this.nvim, id);
|
|
}
|
|
async _setupDynamicAutocmd() {
|
|
let schemes = this.schemeProviderMap.keys();
|
|
let cmds = [];
|
|
for (let scheme of schemes) {
|
|
cmds.push(`autocmd BufReadCmd,FileReadCmd,SourceCmd ${scheme}://* call coc#rpc#request('CocAutocmd', ['BufReadCmd','${scheme}', expand('<amatch>')])`);
|
|
}
|
|
for (let [id, autocmd] of this.autocmds.entries()) {
|
|
let args = autocmd.arglist && autocmd.arglist.length ? ', ' + autocmd.arglist.join(', ') : '';
|
|
let event = Array.isArray(autocmd.event) ? autocmd.event.join(',') : autocmd.event;
|
|
let pattern = '*';
|
|
if (/\buser\b/i.test(event)) {
|
|
pattern = '';
|
|
}
|
|
cmds.push(`autocmd ${event} ${pattern} call coc#rpc#${autocmd.request ? 'request' : 'notify'}('doAutocmd', [${id}${args}])`);
|
|
}
|
|
for (let key of this.watchedOptions) {
|
|
cmds.push(`autocmd OptionSet ${key} call coc#rpc#notify('OptionSet',[expand('<amatch>'), v:option_old, v:option_new])`);
|
|
}
|
|
let content = `
|
|
augroup coc_autocmd
|
|
autocmd!
|
|
${cmds.join('\n')}
|
|
augroup end`;
|
|
try {
|
|
let filepath = path_1.default.join(os_1.default.tmpdir(), `coc-${process.pid}.vim`);
|
|
await fs_2.writeFile(filepath, content);
|
|
let cmd = `source ${filepath}`;
|
|
const isCygwin = await this.nvim.eval('has("win32unix")');
|
|
if (isCygwin && index_1.platform.isWindows) {
|
|
cmd = `execute "source" . substitute(system('cygpath ${filepath.replace(/\\/g, '/')}'), '\\n', '', 'g')`;
|
|
}
|
|
await this.nvim.command(cmd);
|
|
}
|
|
catch (e) {
|
|
this.showMessage(`Can't create tmp file: ${e.message}`, 'error');
|
|
}
|
|
}
|
|
async onBufReadCmd(scheme, uri) {
|
|
let provider = this.schemeProviderMap.get(scheme);
|
|
if (!provider) {
|
|
this.showMessage(`Provider for ${scheme} not found`, 'error');
|
|
return;
|
|
}
|
|
let tokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource();
|
|
let content = await Promise.resolve(provider.provideTextDocumentContent(vscode_uri_1.URI.parse(uri), tokenSource.token));
|
|
let buf = await this.nvim.buffer;
|
|
await buf.setLines(content.split('\n'), {
|
|
start: 0,
|
|
end: -1,
|
|
strictIndexing: false
|
|
});
|
|
setTimeout(async () => {
|
|
await events_1.default.fire('BufCreate', [buf.id]);
|
|
}, 30);
|
|
}
|
|
async attach() {
|
|
if (this._attached)
|
|
return;
|
|
this._attached = true;
|
|
let buffers = await this.nvim.buffers;
|
|
let bufnr = this.bufnr = await this.nvim.call('bufnr', '%');
|
|
await Promise.all(buffers.map(buf => {
|
|
return this.onBufCreate(buf);
|
|
}));
|
|
if (!this._initialized) {
|
|
this._onDidWorkspaceInitialized.fire(void 0);
|
|
this._initialized = true;
|
|
}
|
|
await events_1.default.fire('BufEnter', [bufnr]);
|
|
let winid = await this.nvim.call('win_getid');
|
|
await events_1.default.fire('BufWinEnter', [bufnr, winid]);
|
|
}
|
|
validteDocumentChanges(documentChanges) {
|
|
if (!documentChanges)
|
|
return true;
|
|
for (let change of documentChanges) {
|
|
if (index_1.isDocumentEdit(change)) {
|
|
let { textDocument } = change;
|
|
let { uri, version } = textDocument;
|
|
let doc = this.getDocument(uri);
|
|
if (version && !doc) {
|
|
this.showMessage(`${uri} not opened.`, 'error');
|
|
return false;
|
|
}
|
|
if (version && doc.version != version) {
|
|
this.showMessage(`${uri} changed before apply edit`, 'error');
|
|
return false;
|
|
}
|
|
if (!version && !doc) {
|
|
if (!uri.startsWith('file')) {
|
|
this.showMessage(`Can't apply edits to ${uri}.`, 'error');
|
|
return false;
|
|
}
|
|
let exists = fs_1.default.existsSync(vscode_uri_1.URI.parse(uri).fsPath);
|
|
if (!exists) {
|
|
this.showMessage(`File ${uri} not exists.`, 'error');
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
else if (vscode_languageserver_protocol_1.CreateFile.is(change) || vscode_languageserver_protocol_1.DeleteFile.is(change)) {
|
|
if (!fs_2.isFile(change.uri)) {
|
|
this.showMessage(`Chagne of scheme ${change.uri} not supported`, 'error');
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
createConfigurations() {
|
|
let home = process.env.COC_VIMCONFIG || path_1.default.join(os_1.default.homedir(), '.vim');
|
|
if (global.hasOwnProperty('__TEST__')) {
|
|
home = path_1.default.join(this.pluginRoot, 'src/__tests__');
|
|
}
|
|
let userConfigFile = path_1.default.join(home, CONFIG_FILE_NAME);
|
|
return new configuration_1.default(userConfigFile, new shape_1.default(this));
|
|
}
|
|
// events for sync buffer of vim
|
|
attachChangedEvents() {
|
|
if (this.isVim) {
|
|
const onChange = async (bufnr) => {
|
|
let doc = this.getDocument(bufnr);
|
|
if (doc && doc.shouldAttach)
|
|
doc.fetchContent();
|
|
};
|
|
events_1.default.on('TextChangedI', onChange, null, this.disposables);
|
|
events_1.default.on('TextChanged', onChange, null, this.disposables);
|
|
}
|
|
}
|
|
async onBufCreate(buf) {
|
|
let buffer = typeof buf === 'number' ? this.nvim.createBuffer(buf) : buf;
|
|
let bufnr = buffer.id;
|
|
if (this.creatingSources.has(bufnr))
|
|
return;
|
|
let document = this.getDocument(bufnr);
|
|
let source = new vscode_languageserver_protocol_1.CancellationTokenSource();
|
|
try {
|
|
if (document)
|
|
this.onBufUnload(bufnr, true).logError();
|
|
document = new document_1.default(buffer, this._env);
|
|
let token = source.token;
|
|
this.creatingSources.set(bufnr, source);
|
|
let created = await document.init(this.nvim, token);
|
|
if (!created)
|
|
document = null;
|
|
}
|
|
catch (e) {
|
|
logger.error('Error on create buffer:', e);
|
|
document = null;
|
|
}
|
|
if (this.creatingSources.get(bufnr) == source) {
|
|
source.dispose();
|
|
this.creatingSources.delete(bufnr);
|
|
}
|
|
if (!document || !document.textDocument)
|
|
return;
|
|
this.buffers.set(bufnr, document);
|
|
if (document.enabled) {
|
|
document.onDocumentDetach(uri => {
|
|
let doc = this.getDocument(uri);
|
|
if (doc)
|
|
this.onBufUnload(doc.bufnr).logError();
|
|
});
|
|
}
|
|
if (document.buftype == '' && document.schema == 'file') {
|
|
let config = this.getConfiguration('workspace');
|
|
let filetypes = config.get('ignoredFiletypes', []);
|
|
if (filetypes.indexOf(document.filetype) == -1) {
|
|
let root = this.resolveRoot(document);
|
|
if (root) {
|
|
this.addWorkspaceFolder(root);
|
|
if (this.bufnr == buffer.id) {
|
|
this._root = root;
|
|
}
|
|
}
|
|
}
|
|
this.configurations.checkFolderConfiguration(document.uri);
|
|
}
|
|
if (document.enabled) {
|
|
this._onDidOpenDocument.fire(document.textDocument);
|
|
document.onDocumentChange(e => this._onDidChangeDocument.fire(e));
|
|
}
|
|
logger.debug('buffer created', buffer.id);
|
|
}
|
|
async onBufEnter(bufnr) {
|
|
this.bufnr = bufnr;
|
|
let doc = this.getDocument(bufnr);
|
|
if (doc) {
|
|
this.configurations.setFolderConfiguration(doc.uri);
|
|
let workspaceFolder = this.getWorkspaceFolder(doc.uri);
|
|
if (workspaceFolder)
|
|
this._root = vscode_uri_1.URI.parse(workspaceFolder.uri).fsPath;
|
|
}
|
|
}
|
|
async onCursorMoved(bufnr) {
|
|
this.bufnr = bufnr;
|
|
await this.checkBuffer(bufnr);
|
|
}
|
|
async onBufWritePost(bufnr) {
|
|
let doc = this.buffers.get(bufnr);
|
|
if (!doc)
|
|
return;
|
|
this._onDidSaveDocument.fire(doc.textDocument);
|
|
}
|
|
async onBufUnload(bufnr, recreate = false) {
|
|
logger.debug('buffer unload', bufnr);
|
|
if (!recreate) {
|
|
let source = this.creatingSources.get(bufnr);
|
|
if (source) {
|
|
source.cancel();
|
|
this.creatingSources.delete(bufnr);
|
|
}
|
|
}
|
|
if (this.terminals.has(bufnr)) {
|
|
let terminal = this.terminals.get(bufnr);
|
|
this._onDidCloseTerminal.fire(terminal);
|
|
this.terminals.delete(bufnr);
|
|
}
|
|
let doc = this.buffers.get(bufnr);
|
|
if (doc) {
|
|
this._onDidCloseDocument.fire(doc.textDocument);
|
|
this.buffers.delete(bufnr);
|
|
if (!recreate)
|
|
doc.detach();
|
|
}
|
|
await index_1.wait(10);
|
|
}
|
|
async onBufWritePre(bufnr) {
|
|
let doc = this.buffers.get(bufnr);
|
|
if (!doc)
|
|
return;
|
|
let event = {
|
|
document: doc.textDocument,
|
|
reason: vscode_languageserver_protocol_1.TextDocumentSaveReason.Manual
|
|
};
|
|
this._onWillSaveDocument.fire(event);
|
|
if (this.willSaveUntilHandler.hasCallback) {
|
|
await this.willSaveUntilHandler.handeWillSaveUntil(event);
|
|
}
|
|
}
|
|
onDirChanged(cwd) {
|
|
if (cwd == this._cwd)
|
|
return;
|
|
this._cwd = cwd;
|
|
}
|
|
onFileTypeChange(filetype, bufnr) {
|
|
let doc = this.getDocument(bufnr);
|
|
if (!doc)
|
|
return;
|
|
let converted = doc.convertFiletype(filetype);
|
|
if (converted == doc.filetype)
|
|
return;
|
|
this._onDidCloseDocument.fire(doc.textDocument);
|
|
doc.setFiletype(filetype);
|
|
this._onDidOpenDocument.fire(doc.textDocument);
|
|
}
|
|
async checkBuffer(bufnr) {
|
|
if (this._disposed)
|
|
return;
|
|
let doc = this.getDocument(bufnr);
|
|
if (!doc && !this.creatingSources.has(bufnr))
|
|
await this.onBufCreate(bufnr);
|
|
}
|
|
async getFileEncoding() {
|
|
let encoding = await this.nvim.getOption('fileencoding');
|
|
return encoding ? encoding : 'utf-8';
|
|
}
|
|
resolveRoot(document) {
|
|
let types = [types_1.PatternType.Buffer, types_1.PatternType.LanguageServer, types_1.PatternType.Global];
|
|
let u = vscode_uri_1.URI.parse(document.uri);
|
|
let dir = path_1.default.dirname(u.fsPath);
|
|
let { cwd } = this;
|
|
for (let patternType of types) {
|
|
let patterns = this.getRootPatterns(document, patternType);
|
|
if (patterns && patterns.length) {
|
|
let root = fs_2.resolveRoot(dir, patterns, cwd);
|
|
if (root)
|
|
return root;
|
|
}
|
|
}
|
|
if (this.cwd != os_1.default.homedir() && fs_2.isParentFolder(this.cwd, dir))
|
|
return this.cwd;
|
|
return null;
|
|
}
|
|
getRootPatterns(document, patternType) {
|
|
let { uri } = document;
|
|
if (patternType == types_1.PatternType.Buffer)
|
|
return document.getVar('root_patterns', []) || [];
|
|
if (patternType == types_1.PatternType.LanguageServer)
|
|
return this.getServerRootPatterns(document.filetype);
|
|
const preferences = this.getConfiguration('coc.preferences', uri);
|
|
return preferences.get('rootPatterns', ['.vim', '.git', '.hg', '.projections.json']).slice();
|
|
}
|
|
async renameCurrent() {
|
|
let { nvim } = this;
|
|
let bufnr = await nvim.call('bufnr', '%');
|
|
let cwd = await nvim.call('getcwd');
|
|
let doc = this.getDocument(bufnr);
|
|
if (!doc || doc.buftype != '' || doc.schema != 'file') {
|
|
nvim.errWriteLine('current buffer is not file.');
|
|
return;
|
|
}
|
|
let oldPath = vscode_uri_1.URI.parse(doc.uri).fsPath;
|
|
let newPath = await nvim.call('input', ['New path: ', oldPath, 'file']);
|
|
newPath = newPath ? newPath.trim() : null;
|
|
if (newPath == oldPath || !newPath)
|
|
return;
|
|
let lines = await doc.buffer.lines;
|
|
let exists = fs_1.default.existsSync(oldPath);
|
|
if (exists) {
|
|
let modified = await nvim.eval('&modified');
|
|
if (modified)
|
|
await nvim.command('noa w');
|
|
if (oldPath.toLowerCase() != newPath.toLowerCase() && fs_1.default.existsSync(newPath)) {
|
|
let overwrite = await this.showPrompt(`${newPath} exists, overwrite?`);
|
|
if (!overwrite)
|
|
return;
|
|
fs_1.default.unlinkSync(newPath);
|
|
}
|
|
fs_1.default.renameSync(oldPath, newPath);
|
|
}
|
|
let filepath = fs_2.isParentFolder(cwd, newPath) ? path_1.default.relative(cwd, newPath) : newPath;
|
|
let cursor = await nvim.call('getcurpos');
|
|
nvim.pauseNotification();
|
|
if (oldPath.toLowerCase() == newPath.toLowerCase()) {
|
|
nvim.command(`keepalt ${bufnr}bwipeout!`, true);
|
|
nvim.call('coc#util#open_file', ['keepalt edit', filepath], true);
|
|
}
|
|
else {
|
|
nvim.call('coc#util#open_file', ['keepalt edit', filepath], true);
|
|
nvim.command(`${bufnr}bwipeout!`, true);
|
|
}
|
|
if (!exists && lines.join('\n') != '\n') {
|
|
nvim.call('append', [0, lines], true);
|
|
nvim.command('normal! Gdd', true);
|
|
}
|
|
nvim.call('setpos', ['.', cursor], true);
|
|
await nvim.resumeNotification();
|
|
}
|
|
setMessageLevel() {
|
|
let config = this.getConfiguration('coc.preferences');
|
|
let level = config.get('messageLevel', 'more');
|
|
switch (level) {
|
|
case 'error':
|
|
this.messageLevel = types_1.MessageLevel.Error;
|
|
break;
|
|
case 'warning':
|
|
this.messageLevel = types_1.MessageLevel.Warning;
|
|
break;
|
|
default:
|
|
this.messageLevel = types_1.MessageLevel.More;
|
|
}
|
|
}
|
|
mergeDocumentChanges(changes) {
|
|
let res = [];
|
|
let documentEdits = [];
|
|
for (let change of changes) {
|
|
if (index_1.isDocumentEdit(change)) {
|
|
let { edits, textDocument } = change;
|
|
let documentEdit = documentEdits.find(o => o.textDocument.uri == textDocument.uri && o.textDocument.version === textDocument.version);
|
|
if (documentEdit) {
|
|
documentEdit.edits.push(...edits);
|
|
}
|
|
else {
|
|
documentEdits.push(change);
|
|
}
|
|
}
|
|
else {
|
|
res.push(change);
|
|
}
|
|
}
|
|
res.push(...documentEdits);
|
|
return res;
|
|
}
|
|
get folderPaths() {
|
|
return this.workspaceFolders.map(f => vscode_uri_1.URI.parse(f.uri).fsPath);
|
|
}
|
|
removeWorkspaceFolder(fsPath) {
|
|
let idx = this._workspaceFolders.findIndex(f => vscode_uri_1.URI.parse(f.uri).fsPath == fsPath);
|
|
if (idx != -1) {
|
|
let folder = this._workspaceFolders[idx];
|
|
this._workspaceFolders.splice(idx, 1);
|
|
this._onDidChangeWorkspaceFolders.fire({
|
|
removed: [folder],
|
|
added: []
|
|
});
|
|
}
|
|
}
|
|
renameWorkspaceFolder(oldPath, newPath) {
|
|
let idx = this._workspaceFolders.findIndex(f => vscode_uri_1.URI.parse(f.uri).fsPath == oldPath);
|
|
if (idx == -1)
|
|
return;
|
|
let removed = this._workspaceFolders[idx];
|
|
let added = {
|
|
uri: vscode_uri_1.URI.file(newPath).toString(),
|
|
name: path_1.default.dirname(newPath)
|
|
};
|
|
this._workspaceFolders.splice(idx, 1);
|
|
this._workspaceFolders.push(added);
|
|
this._onDidChangeWorkspaceFolders.fire({
|
|
removed: [removed],
|
|
added: [added]
|
|
});
|
|
}
|
|
addRootPatterns(filetype, rootPatterns) {
|
|
let patterns = this.rootPatterns.get(filetype) || [];
|
|
for (let p of rootPatterns) {
|
|
if (patterns.indexOf(p) == -1) {
|
|
patterns.push(p);
|
|
}
|
|
}
|
|
this.rootPatterns.set(filetype, patterns);
|
|
}
|
|
get insertMode() {
|
|
return this._insertMode;
|
|
}
|
|
getDocumentOption(name, doc) {
|
|
if (doc) {
|
|
return doc.buffer.getOption(name).catch(_e => {
|
|
return this.nvim.getOption(name);
|
|
});
|
|
}
|
|
return this.nvim.getOption(name);
|
|
}
|
|
addWorkspaceFolder(rootPath) {
|
|
if (rootPath == os_1.default.homedir())
|
|
return;
|
|
let { _workspaceFolders } = this;
|
|
let uri = vscode_uri_1.URI.file(rootPath).toString();
|
|
let workspaceFolder = { uri, name: path_1.default.basename(rootPath) };
|
|
if (_workspaceFolders.findIndex(o => o.uri == uri) == -1) {
|
|
_workspaceFolders.push(workspaceFolder);
|
|
if (this._initialized) {
|
|
this._onDidChangeWorkspaceFolders.fire({
|
|
added: [workspaceFolder],
|
|
removed: []
|
|
});
|
|
}
|
|
}
|
|
return workspaceFolder;
|
|
}
|
|
getServerRootPatterns(filetype) {
|
|
let lspConfig = this.getConfiguration().get('languageserver', {});
|
|
let patterns = [];
|
|
for (let key of Object.keys(lspConfig)) {
|
|
let config = lspConfig[key];
|
|
let { filetypes, rootPatterns } = config;
|
|
if (filetypes && rootPatterns && filetypes.indexOf(filetype) !== -1) {
|
|
patterns.push(...rootPatterns);
|
|
}
|
|
}
|
|
patterns = patterns.concat(this.rootPatterns.get(filetype) || []);
|
|
return patterns.length ? array_1.distinct(patterns) : null;
|
|
}
|
|
}
|
|
exports.Workspace = Workspace;
|
|
exports.default = new Workspace();
|
|
//# sourceMappingURL=workspace.js.map
|
|
|
|
/***/ }),
|
|
/* 188 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const os_1 = tslib_1.__importDefault(__webpack_require__(56));
|
|
const fs_1 = tslib_1.__importDefault(__webpack_require__(55));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const types_1 = __webpack_require__(189);
|
|
const object_1 = __webpack_require__(190);
|
|
const util_1 = __webpack_require__(174);
|
|
const configuration_1 = __webpack_require__(192);
|
|
const model_1 = __webpack_require__(193);
|
|
const util_2 = __webpack_require__(194);
|
|
const is_1 = __webpack_require__(191);
|
|
const fs_2 = __webpack_require__(200);
|
|
const logger = __webpack_require__(186)('configurations');
|
|
function lookUp(tree, key) {
|
|
if (key) {
|
|
if (tree && tree.hasOwnProperty(key))
|
|
return tree[key];
|
|
const parts = key.split('.');
|
|
let node = tree;
|
|
for (let i = 0; node && i < parts.length; i++) {
|
|
node = node[parts[i]];
|
|
}
|
|
return node;
|
|
}
|
|
return tree;
|
|
}
|
|
class Configurations {
|
|
constructor(userConfigFile, _proxy) {
|
|
this.userConfigFile = userConfigFile;
|
|
this._proxy = _proxy;
|
|
this._errorItems = [];
|
|
this._folderConfigurations = new Map();
|
|
this._onError = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onChange = new vscode_languageserver_protocol_1.Emitter();
|
|
this.disposables = [];
|
|
this.onError = this._onError.event;
|
|
this.onDidChange = this._onChange.event;
|
|
let user = this.parseContentFromFile(userConfigFile);
|
|
let data = {
|
|
defaults: util_2.loadDefaultConfigurations(),
|
|
user,
|
|
workspace: { contents: {} }
|
|
};
|
|
this._configuration = Configurations.parse(data);
|
|
this.watchFile(userConfigFile, types_1.ConfigurationTarget.User);
|
|
}
|
|
parseContentFromFile(filepath) {
|
|
if (!filepath)
|
|
return { contents: {} };
|
|
let uri = vscode_uri_1.URI.file(filepath).toString();
|
|
this._errorItems = this._errorItems.filter(o => o.location.uri != uri);
|
|
let res = util_2.parseContentFromFile(filepath, errors => {
|
|
this._errorItems.push(...errors);
|
|
});
|
|
this._onError.fire(this._errorItems);
|
|
return res;
|
|
}
|
|
get errorItems() {
|
|
return this._errorItems;
|
|
}
|
|
get foldConfigurations() {
|
|
return this._folderConfigurations;
|
|
}
|
|
// used for extensions, no change event fired
|
|
extendsDefaults(props) {
|
|
let { defaults } = this._configuration;
|
|
let { contents } = defaults;
|
|
contents = object_1.deepClone(contents);
|
|
Object.keys(props).forEach(key => {
|
|
util_2.addToValueTree(contents, key, props[key], msg => {
|
|
logger.error(msg); // tslint:disable-line
|
|
});
|
|
});
|
|
let data = {
|
|
defaults: { contents },
|
|
user: this._configuration.user,
|
|
workspace: this._configuration.workspace
|
|
};
|
|
this._configuration = Configurations.parse(data);
|
|
}
|
|
// change user configuration, without change file
|
|
updateUserConfig(props) {
|
|
if (!props || Object.keys(props).length == 0)
|
|
return;
|
|
let { user } = this._configuration;
|
|
let model = user.clone();
|
|
Object.keys(props).forEach(key => {
|
|
let val = props[key];
|
|
if (val === undefined) {
|
|
model.removeValue(key);
|
|
}
|
|
else if (is_1.objectLiteral(val)) {
|
|
for (let k of Object.keys(val)) {
|
|
model.setValue(`${key}.${k}`, val[k]);
|
|
}
|
|
}
|
|
else {
|
|
model.setValue(key, val);
|
|
}
|
|
});
|
|
this.changeConfiguration(types_1.ConfigurationTarget.User, model);
|
|
}
|
|
get defaults() {
|
|
return this._configuration.defaults;
|
|
}
|
|
get user() {
|
|
return this._configuration.user;
|
|
}
|
|
get workspace() {
|
|
return this._configuration.workspace;
|
|
}
|
|
addFolderFile(filepath) {
|
|
let { _folderConfigurations } = this;
|
|
if (_folderConfigurations.has(filepath))
|
|
return;
|
|
if (path_1.default.resolve(filepath, '../..') == os_1.default.homedir())
|
|
return;
|
|
let model = this.parseContentFromFile(filepath);
|
|
this.watchFile(filepath, types_1.ConfigurationTarget.Workspace);
|
|
this.changeConfiguration(types_1.ConfigurationTarget.Workspace, model, filepath);
|
|
}
|
|
watchFile(filepath, target) {
|
|
if (!fs_1.default.existsSync(filepath))
|
|
return;
|
|
if (global.hasOwnProperty('__TEST__'))
|
|
return;
|
|
let disposable = util_1.watchFile(filepath, () => {
|
|
let model = this.parseContentFromFile(filepath);
|
|
this.changeConfiguration(target, model, filepath);
|
|
});
|
|
this.disposables.push(disposable);
|
|
}
|
|
// create new configuration and fire change event
|
|
changeConfiguration(target, model, configFile) {
|
|
let { defaults, user, workspace } = this._configuration;
|
|
let { workspaceConfigFile } = this;
|
|
let data = {
|
|
defaults: target == types_1.ConfigurationTarget.Global ? model : defaults,
|
|
user: target == types_1.ConfigurationTarget.User ? model : user,
|
|
workspace: target == types_1.ConfigurationTarget.Workspace ? model : workspace,
|
|
};
|
|
let configuration = Configurations.parse(data);
|
|
let changed = util_2.getChangedKeys(this._configuration.getValue(), configuration.getValue());
|
|
if (target == types_1.ConfigurationTarget.Workspace && configFile) {
|
|
this._folderConfigurations.set(configFile, new model_1.ConfigurationModel(model.contents));
|
|
this.workspaceConfigFile = configFile;
|
|
}
|
|
if (changed.length == 0)
|
|
return;
|
|
this._configuration = configuration;
|
|
this._onChange.fire({
|
|
affectsConfiguration: (section, resource) => {
|
|
if (!resource || target != types_1.ConfigurationTarget.Workspace)
|
|
return changed.indexOf(section) !== -1;
|
|
let u = vscode_uri_1.URI.parse(resource);
|
|
if (u.scheme !== 'file')
|
|
return changed.indexOf(section) !== -1;
|
|
let filepath = u.fsPath;
|
|
let preRoot = workspaceConfigFile ? path_1.default.resolve(workspaceConfigFile, '../..') : '';
|
|
if (configFile && !fs_2.isParentFolder(preRoot, filepath) && !fs_2.isParentFolder(path_1.default.resolve(configFile, '../..'), filepath)) {
|
|
return false;
|
|
}
|
|
return changed.indexOf(section) !== -1;
|
|
}
|
|
});
|
|
}
|
|
setFolderConfiguration(uri) {
|
|
let u = vscode_uri_1.URI.parse(uri);
|
|
if (u.scheme != 'file')
|
|
return;
|
|
let filepath = u.fsPath;
|
|
for (let [configFile, model] of this.foldConfigurations) {
|
|
let root = path_1.default.resolve(configFile, '../..');
|
|
if (fs_2.isParentFolder(root, filepath) && this.workspaceConfigFile != configFile) {
|
|
this.changeConfiguration(types_1.ConfigurationTarget.Workspace, model, configFile);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
hasFolderConfiguration(filepath) {
|
|
let { folders } = this;
|
|
return folders.findIndex(f => fs_2.isParentFolder(f, filepath)) !== -1;
|
|
}
|
|
getConfigFile(target) {
|
|
if (target == types_1.ConfigurationTarget.Global)
|
|
return null;
|
|
if (target == types_1.ConfigurationTarget.User)
|
|
return this.userConfigFile;
|
|
return this.workspaceConfigFile;
|
|
}
|
|
get folders() {
|
|
let res = [];
|
|
let { _folderConfigurations } = this;
|
|
for (let folder of _folderConfigurations.keys()) {
|
|
res.push(path_1.default.resolve(folder, '../..'));
|
|
}
|
|
return res;
|
|
}
|
|
get configuration() {
|
|
return this._configuration;
|
|
}
|
|
/**
|
|
* getConfiguration
|
|
*
|
|
* @public
|
|
* @param {string} section
|
|
* @returns {WorkspaceConfiguration}
|
|
*/
|
|
getConfiguration(section, resource) {
|
|
let configuration;
|
|
if (resource) {
|
|
let { defaults, user } = this._configuration;
|
|
configuration = new configuration_1.Configuration(defaults, user, this.getFolderConfiguration(resource));
|
|
}
|
|
else {
|
|
configuration = this._configuration;
|
|
}
|
|
const config = Object.freeze(lookUp(configuration.getValue(null), section));
|
|
const result = {
|
|
has(key) {
|
|
return typeof lookUp(config, key) !== 'undefined';
|
|
},
|
|
get: (key, defaultValue) => {
|
|
let result = lookUp(config, key);
|
|
if (result == null)
|
|
return defaultValue;
|
|
return result;
|
|
},
|
|
update: (key, value, isUser = false) => {
|
|
let s = section ? `${section}.${key}` : key;
|
|
let target = isUser ? types_1.ConfigurationTarget.User : types_1.ConfigurationTarget.Workspace;
|
|
let model = target == types_1.ConfigurationTarget.User ? this.user.clone() : this.workspace.clone();
|
|
if (value == undefined) {
|
|
model.removeValue(s);
|
|
}
|
|
else {
|
|
model.setValue(s, value);
|
|
}
|
|
if (!this.workspaceConfigFile && this._proxy) {
|
|
let file = this.workspaceConfigFile = this._proxy.workspaceConfigFile;
|
|
if (!fs_1.default.existsSync(file)) {
|
|
let folder = path_1.default.dirname(file);
|
|
if (!fs_1.default.existsSync(folder))
|
|
fs_1.default.mkdirSync(folder);
|
|
fs_1.default.writeFileSync(file, '{}', { encoding: 'utf8' });
|
|
}
|
|
}
|
|
this.changeConfiguration(target, model, target == types_1.ConfigurationTarget.Workspace ? this.workspaceConfigFile : this.userConfigFile);
|
|
if (this._proxy && !global.hasOwnProperty('__TEST__')) {
|
|
if (value == undefined) {
|
|
this._proxy.$removeConfigurationOption(target, s);
|
|
}
|
|
else {
|
|
this._proxy.$updateConfigurationOption(target, s, value);
|
|
}
|
|
}
|
|
},
|
|
inspect: (key) => {
|
|
key = section ? `${section}.${key}` : key;
|
|
const config = this._configuration.inspect(key);
|
|
if (config) {
|
|
return {
|
|
key,
|
|
defaultValue: config.default,
|
|
globalValue: config.user,
|
|
workspaceValue: config.workspace,
|
|
};
|
|
}
|
|
return undefined;
|
|
}
|
|
};
|
|
Object.defineProperty(result, 'has', {
|
|
enumerable: false
|
|
});
|
|
Object.defineProperty(result, 'get', {
|
|
enumerable: false
|
|
});
|
|
Object.defineProperty(result, 'update', {
|
|
enumerable: false
|
|
});
|
|
Object.defineProperty(result, 'inspect', {
|
|
enumerable: false
|
|
});
|
|
if (typeof config === 'object') {
|
|
object_1.mixin(result, config, false);
|
|
}
|
|
return object_1.deepFreeze(result);
|
|
}
|
|
getFolderConfiguration(uri) {
|
|
let u = vscode_uri_1.URI.parse(uri);
|
|
if (u.scheme != 'file')
|
|
return new model_1.ConfigurationModel();
|
|
let filepath = u.fsPath;
|
|
for (let [configFile, model] of this.foldConfigurations) {
|
|
let root = path_1.default.resolve(configFile, '../..');
|
|
if (fs_2.isParentFolder(root, filepath))
|
|
return model;
|
|
}
|
|
return new model_1.ConfigurationModel();
|
|
}
|
|
checkFolderConfiguration(uri) {
|
|
let u = vscode_uri_1.URI.parse(uri);
|
|
if (u.scheme != 'file')
|
|
return;
|
|
let rootPath = path_1.default.dirname(u.fsPath);
|
|
if (!this.hasFolderConfiguration(rootPath)) {
|
|
let folder = fs_2.findUp('.vim', rootPath);
|
|
if (folder && folder != os_1.default.homedir()) {
|
|
let file = path_1.default.join(folder, 'coc-settings.json');
|
|
if (fs_1.default.existsSync(file)) {
|
|
this.addFolderFile(file);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
this.setFolderConfiguration(uri);
|
|
}
|
|
}
|
|
static parse(data) {
|
|
const defaultConfiguration = new model_1.ConfigurationModel(data.defaults.contents);
|
|
const userConfiguration = new model_1.ConfigurationModel(data.user.contents);
|
|
const workspaceConfiguration = new model_1.ConfigurationModel(data.workspace.contents);
|
|
return new configuration_1.Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, new model_1.ConfigurationModel());
|
|
}
|
|
dispose() {
|
|
util_1.disposeAll(this.disposables);
|
|
}
|
|
}
|
|
exports.default = Configurations;
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
/* 189 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
var PatternType;
|
|
(function (PatternType) {
|
|
PatternType[PatternType["Buffer"] = 0] = "Buffer";
|
|
PatternType[PatternType["LanguageServer"] = 1] = "LanguageServer";
|
|
PatternType[PatternType["Global"] = 2] = "Global";
|
|
})(PatternType = exports.PatternType || (exports.PatternType = {}));
|
|
var SourceType;
|
|
(function (SourceType) {
|
|
SourceType[SourceType["Native"] = 0] = "Native";
|
|
SourceType[SourceType["Remote"] = 1] = "Remote";
|
|
SourceType[SourceType["Service"] = 2] = "Service";
|
|
})(SourceType = exports.SourceType || (exports.SourceType = {}));
|
|
var MessageLevel;
|
|
(function (MessageLevel) {
|
|
MessageLevel[MessageLevel["More"] = 0] = "More";
|
|
MessageLevel[MessageLevel["Warning"] = 1] = "Warning";
|
|
MessageLevel[MessageLevel["Error"] = 2] = "Error";
|
|
})(MessageLevel = exports.MessageLevel || (exports.MessageLevel = {}));
|
|
var ConfigurationTarget;
|
|
(function (ConfigurationTarget) {
|
|
ConfigurationTarget[ConfigurationTarget["Global"] = 0] = "Global";
|
|
ConfigurationTarget[ConfigurationTarget["User"] = 1] = "User";
|
|
ConfigurationTarget[ConfigurationTarget["Workspace"] = 2] = "Workspace";
|
|
})(ConfigurationTarget = exports.ConfigurationTarget || (exports.ConfigurationTarget = {}));
|
|
var DiagnosticKind;
|
|
(function (DiagnosticKind) {
|
|
DiagnosticKind[DiagnosticKind["Syntax"] = 0] = "Syntax";
|
|
DiagnosticKind[DiagnosticKind["Semantic"] = 1] = "Semantic";
|
|
DiagnosticKind[DiagnosticKind["Suggestion"] = 2] = "Suggestion";
|
|
})(DiagnosticKind = exports.DiagnosticKind || (exports.DiagnosticKind = {}));
|
|
var ServiceStat;
|
|
(function (ServiceStat) {
|
|
ServiceStat[ServiceStat["Initial"] = 0] = "Initial";
|
|
ServiceStat[ServiceStat["Starting"] = 1] = "Starting";
|
|
ServiceStat[ServiceStat["StartFailed"] = 2] = "StartFailed";
|
|
ServiceStat[ServiceStat["Running"] = 3] = "Running";
|
|
ServiceStat[ServiceStat["Stopping"] = 4] = "Stopping";
|
|
ServiceStat[ServiceStat["Stopped"] = 5] = "Stopped";
|
|
})(ServiceStat = exports.ServiceStat || (exports.ServiceStat = {}));
|
|
//# sourceMappingURL=types.js.map
|
|
|
|
/***/ }),
|
|
/* 190 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const Is = tslib_1.__importStar(__webpack_require__(191));
|
|
function deepClone(obj) {
|
|
if (!obj || typeof obj !== 'object') {
|
|
return obj;
|
|
}
|
|
if (obj instanceof RegExp) {
|
|
// See https://github.com/Microsoft/TypeScript/issues/10990
|
|
return obj;
|
|
}
|
|
const result = Array.isArray(obj) ? [] : {};
|
|
Object.keys(obj).forEach(key => {
|
|
if (obj[key] && typeof obj[key] === 'object') {
|
|
result[key] = deepClone(obj[key]);
|
|
}
|
|
else {
|
|
result[key] = obj[key];
|
|
}
|
|
});
|
|
return result;
|
|
}
|
|
exports.deepClone = deepClone;
|
|
const _hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
function deepFreeze(obj) {
|
|
if (!obj || typeof obj !== 'object') {
|
|
return obj;
|
|
}
|
|
const stack = [obj];
|
|
while (stack.length > 0) {
|
|
let obj = stack.shift();
|
|
Object.freeze(obj);
|
|
for (const key in obj) {
|
|
if (_hasOwnProperty.call(obj, key)) {
|
|
let prop = obj[key];
|
|
if (typeof prop === 'object' && !Object.isFrozen(prop)) {
|
|
stack.push(prop);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
exports.deepFreeze = deepFreeze;
|
|
/**
|
|
* Copies all properties of source into destination. The optional parameter "overwrite" allows to control
|
|
* if existing properties on the destination should be overwritten or not. Defaults to true (overwrite).
|
|
*/
|
|
function mixin(destination, source, overwrite = true) {
|
|
if (!Is.objectLiteral(destination)) {
|
|
return source;
|
|
}
|
|
if (Is.objectLiteral(source)) {
|
|
Object.keys(source).forEach(key => {
|
|
if (key in destination) {
|
|
if (overwrite) {
|
|
if (Is.objectLiteral(destination[key]) && Is.objectLiteral(source[key])) {
|
|
mixin(destination[key], source[key], overwrite);
|
|
}
|
|
else {
|
|
destination[key] = source[key];
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
destination[key] = source[key];
|
|
}
|
|
});
|
|
}
|
|
return destination;
|
|
}
|
|
exports.mixin = mixin;
|
|
function equals(one, other) {
|
|
if (one === other) {
|
|
return true;
|
|
}
|
|
if (one === null ||
|
|
one === undefined ||
|
|
other === null ||
|
|
other === undefined) {
|
|
return false;
|
|
}
|
|
if (typeof one !== typeof other) {
|
|
return false;
|
|
}
|
|
if (typeof one !== 'object') {
|
|
return false;
|
|
}
|
|
if (Array.isArray(one) !== Array.isArray(other)) {
|
|
return false;
|
|
}
|
|
let i;
|
|
let key;
|
|
if (Array.isArray(one)) {
|
|
if (one.length !== other.length) {
|
|
return false;
|
|
}
|
|
for (i = 0; i < one.length; i++) {
|
|
if (!equals(one[i], other[i])) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
const oneKeys = [];
|
|
for (key in one) { // tslint:disable-line
|
|
oneKeys.push(key);
|
|
}
|
|
oneKeys.sort();
|
|
const otherKeys = [];
|
|
for (key in other) { // tslint:disable-line
|
|
otherKeys.push(key);
|
|
}
|
|
otherKeys.sort();
|
|
if (!equals(oneKeys, otherKeys)) {
|
|
return false;
|
|
}
|
|
for (i = 0; i < oneKeys.length; i++) {
|
|
if (!equals(one[oneKeys[i]], other[oneKeys[i]])) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
exports.equals = equals;
|
|
//# sourceMappingURL=object.js.map
|
|
|
|
/***/ }),
|
|
/* 191 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
function boolean(value) {
|
|
return typeof value === 'boolean';
|
|
}
|
|
exports.boolean = boolean;
|
|
function string(value) {
|
|
return typeof value === 'string';
|
|
}
|
|
exports.string = string;
|
|
function number(value) {
|
|
return typeof value === 'number';
|
|
}
|
|
exports.number = number;
|
|
function array(array) {
|
|
return Array.isArray(array);
|
|
}
|
|
exports.array = array;
|
|
function func(value) {
|
|
return typeof value == 'function';
|
|
}
|
|
exports.func = func;
|
|
function objectLiteral(obj) {
|
|
return (obj != null &&
|
|
typeof obj === 'object' &&
|
|
!Array.isArray(obj) &&
|
|
!(obj instanceof RegExp) &&
|
|
!(obj instanceof Date));
|
|
}
|
|
exports.objectLiteral = objectLiteral;
|
|
function emptyObject(obj) {
|
|
if (!objectLiteral(obj)) {
|
|
return false;
|
|
}
|
|
for (let key in obj) {
|
|
if (hasOwnProperty.call(obj, key)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
exports.emptyObject = emptyObject;
|
|
function typedArray(value, check) {
|
|
return Array.isArray(value) && value.every(check);
|
|
}
|
|
exports.typedArray = typedArray;
|
|
//# sourceMappingURL=is.js.map
|
|
|
|
/***/ }),
|
|
/* 192 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const model_1 = __webpack_require__(193);
|
|
class Configuration {
|
|
constructor(_defaultConfiguration, _userConfiguration, _workspaceConfiguration, _memoryConfiguration = new model_1.ConfigurationModel()) {
|
|
this._defaultConfiguration = _defaultConfiguration;
|
|
this._userConfiguration = _userConfiguration;
|
|
this._workspaceConfiguration = _workspaceConfiguration;
|
|
this._memoryConfiguration = _memoryConfiguration;
|
|
}
|
|
getConsolidateConfiguration() {
|
|
if (!this._consolidateConfiguration) {
|
|
this._consolidateConfiguration = this._defaultConfiguration.merge(this._userConfiguration, this._workspaceConfiguration, this._memoryConfiguration);
|
|
this._consolidateConfiguration = this._consolidateConfiguration.freeze();
|
|
}
|
|
return this._consolidateConfiguration;
|
|
}
|
|
getValue(section) {
|
|
let configuration = this.getConsolidateConfiguration();
|
|
return configuration.getValue(section);
|
|
}
|
|
inspect(key) {
|
|
const consolidateConfigurationModel = this.getConsolidateConfiguration();
|
|
const { _workspaceConfiguration, _memoryConfiguration } = this;
|
|
return {
|
|
default: this._defaultConfiguration.freeze().getValue(key),
|
|
user: this._userConfiguration.freeze().getValue(key),
|
|
workspace: _workspaceConfiguration.freeze().getValue(key),
|
|
memory: _memoryConfiguration.freeze().getValue(key),
|
|
value: consolidateConfigurationModel.getValue(key)
|
|
};
|
|
}
|
|
get defaults() {
|
|
return this._defaultConfiguration;
|
|
}
|
|
get user() {
|
|
return this._userConfiguration;
|
|
}
|
|
get workspace() {
|
|
return this._workspaceConfiguration;
|
|
}
|
|
toData() {
|
|
return {
|
|
defaults: {
|
|
contents: this._defaultConfiguration.contents
|
|
},
|
|
user: {
|
|
contents: this._userConfiguration.contents
|
|
},
|
|
workspace: {
|
|
contents: this._workspaceConfiguration.contents
|
|
}
|
|
};
|
|
}
|
|
}
|
|
exports.Configuration = Configuration;
|
|
//# sourceMappingURL=configuration.js.map
|
|
|
|
/***/ }),
|
|
/* 193 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const is_1 = __webpack_require__(191);
|
|
const object_1 = __webpack_require__(190);
|
|
const util_1 = __webpack_require__(194);
|
|
class ConfigurationModel {
|
|
constructor(_contents = {}) {
|
|
this._contents = _contents;
|
|
}
|
|
get contents() {
|
|
return this._contents;
|
|
}
|
|
clone() {
|
|
return new ConfigurationModel(object_1.deepClone(this._contents));
|
|
}
|
|
getValue(section) {
|
|
let res = section
|
|
? util_1.getConfigurationValue(this.contents, section)
|
|
: this.contents;
|
|
return res;
|
|
}
|
|
merge(...others) {
|
|
const contents = object_1.deepClone(this.contents);
|
|
for (const other of others) {
|
|
this.mergeContents(contents, other.contents);
|
|
}
|
|
return new ConfigurationModel(contents);
|
|
}
|
|
freeze() {
|
|
if (!Object.isFrozen(this._contents)) {
|
|
Object.freeze(this._contents);
|
|
}
|
|
return this;
|
|
}
|
|
mergeContents(source, target) {
|
|
for (const key of Object.keys(target)) {
|
|
if (key in source) {
|
|
if (is_1.objectLiteral(source[key]) && is_1.objectLiteral(target[key])) {
|
|
this.mergeContents(source[key], target[key]);
|
|
continue;
|
|
}
|
|
}
|
|
source[key] = object_1.deepClone(target[key]);
|
|
}
|
|
}
|
|
// Update methods
|
|
setValue(key, value) {
|
|
util_1.addToValueTree(this.contents, key, value, message => {
|
|
// tslint:disable-next-line:no-console
|
|
console.error(message);
|
|
});
|
|
}
|
|
removeValue(key) {
|
|
util_1.removeFromValueTree(this.contents, key);
|
|
}
|
|
}
|
|
exports.ConfigurationModel = ConfigurationModel;
|
|
//# sourceMappingURL=model.js.map
|
|
|
|
/***/ }),
|
|
/* 194 */
|
|
/***/ (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__(149);
|
|
const jsonc_parser_1 = __webpack_require__(195);
|
|
const is_1 = __webpack_require__(191);
|
|
const object_1 = __webpack_require__(190);
|
|
const fs_1 = tslib_1.__importDefault(__webpack_require__(55));
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const logger = __webpack_require__(186)('configuration-util');
|
|
const isWebpack = typeof __webpack_require__ === "function";
|
|
const pluginRoot = isWebpack ? path_1.default.dirname(__dirname) : path_1.default.resolve(__dirname, '../..');
|
|
function parseContentFromFile(filepath, onError) {
|
|
if (!filepath || !fs_1.default.existsSync(filepath))
|
|
return { contents: {} };
|
|
let content;
|
|
let uri = vscode_uri_1.URI.file(filepath).toString();
|
|
try {
|
|
content = fs_1.default.readFileSync(filepath, 'utf8');
|
|
}
|
|
catch (_e) {
|
|
content = '';
|
|
}
|
|
let [errors, contents] = parseConfiguration(content);
|
|
if (errors && errors.length) {
|
|
onError(convertErrors(uri, content, errors));
|
|
}
|
|
return { contents };
|
|
}
|
|
exports.parseContentFromFile = parseContentFromFile;
|
|
function parseConfiguration(content) {
|
|
if (content.length == 0)
|
|
return [[], {}];
|
|
let errors = [];
|
|
let data = jsonc_parser_1.parse(content, errors, { allowTrailingComma: true });
|
|
function addProperty(current, key, remains, value) {
|
|
if (remains.length == 0) {
|
|
current[key] = convert(value);
|
|
}
|
|
else {
|
|
if (!current[key])
|
|
current[key] = {};
|
|
let o = current[key];
|
|
let first = remains.shift();
|
|
addProperty(o, first, remains, value);
|
|
}
|
|
}
|
|
function convert(obj, split = false) {
|
|
if (!is_1.objectLiteral(obj))
|
|
return obj;
|
|
if (is_1.emptyObject(obj))
|
|
return {};
|
|
let dest = {};
|
|
for (let key of Object.keys(obj)) {
|
|
if (split && key.indexOf('.') !== -1) {
|
|
let parts = key.split('.');
|
|
let first = parts.shift();
|
|
addProperty(dest, first, parts, obj[key]);
|
|
}
|
|
else {
|
|
dest[key] = convert(obj[key]);
|
|
}
|
|
}
|
|
return dest;
|
|
}
|
|
return [errors, convert(data, true)];
|
|
}
|
|
exports.parseConfiguration = parseConfiguration;
|
|
function convertErrors(uri, content, errors) {
|
|
let items = [];
|
|
let document = vscode_languageserver_protocol_1.TextDocument.create(uri, 'json', 0, content);
|
|
for (let err of errors) {
|
|
let msg = 'parse error';
|
|
switch (err.error) {
|
|
case 2:
|
|
msg = 'invalid number';
|
|
break;
|
|
case 8:
|
|
msg = 'close brace expected';
|
|
break;
|
|
case 5:
|
|
msg = 'colon expected';
|
|
break;
|
|
case 6:
|
|
msg = 'comma expected';
|
|
break;
|
|
case 9:
|
|
msg = 'end of file expected';
|
|
break;
|
|
case 16:
|
|
msg = 'invaliad character';
|
|
break;
|
|
case 10:
|
|
msg = 'invalid commment token';
|
|
break;
|
|
case 15:
|
|
msg = 'invalid escape character';
|
|
break;
|
|
case 1:
|
|
msg = 'invalid symbol';
|
|
break;
|
|
case 14:
|
|
msg = 'invalid unicode';
|
|
break;
|
|
case 3:
|
|
msg = 'property name expected';
|
|
break;
|
|
case 13:
|
|
msg = 'unexpected end of number';
|
|
break;
|
|
case 12:
|
|
msg = 'unexpected end of string';
|
|
break;
|
|
case 11:
|
|
msg = 'unexpected end of comment';
|
|
break;
|
|
case 4:
|
|
msg = 'value expected';
|
|
break;
|
|
default:
|
|
msg = 'Unknwn error';
|
|
break;
|
|
}
|
|
let range = {
|
|
start: document.positionAt(err.offset),
|
|
end: document.positionAt(err.offset + err.length),
|
|
};
|
|
let loc = vscode_languageserver_protocol_1.Location.create(uri, range);
|
|
items.push({ location: loc, message: msg });
|
|
}
|
|
return items;
|
|
}
|
|
exports.convertErrors = convertErrors;
|
|
function addToValueTree(settingsTreeRoot, key, value, conflictReporter) {
|
|
const segments = key.split('.');
|
|
const last = segments.pop();
|
|
let curr = settingsTreeRoot;
|
|
for (let i = 0; i < segments.length; i++) {
|
|
let s = segments[i];
|
|
let obj = curr[s];
|
|
switch (typeof obj) {
|
|
case 'function': {
|
|
obj = curr[s] = {};
|
|
break;
|
|
}
|
|
case 'undefined': {
|
|
obj = curr[s] = {};
|
|
break;
|
|
}
|
|
case 'object':
|
|
break;
|
|
default:
|
|
conflictReporter(`Ignoring ${key} as ${segments
|
|
.slice(0, i + 1)
|
|
.join('.')} is ${JSON.stringify(obj)}`);
|
|
return;
|
|
}
|
|
curr = obj;
|
|
}
|
|
if (typeof curr === 'object') {
|
|
curr[last] = value; // workaround https://github.com/Microsoft/vscode/issues/13606
|
|
}
|
|
else {
|
|
conflictReporter(`Ignoring ${key} as ${segments.join('.')} is ${JSON.stringify(curr)}`);
|
|
}
|
|
}
|
|
exports.addToValueTree = addToValueTree;
|
|
function removeFromValueTree(valueTree, key) {
|
|
const segments = key.split('.');
|
|
doRemoveFromValueTree(valueTree, segments);
|
|
}
|
|
exports.removeFromValueTree = removeFromValueTree;
|
|
function doRemoveFromValueTree(valueTree, segments) {
|
|
const first = segments.shift();
|
|
if (segments.length === 0) {
|
|
// Reached last segment
|
|
delete valueTree[first];
|
|
return;
|
|
}
|
|
if (Object.keys(valueTree).indexOf(first) !== -1) {
|
|
const value = valueTree[first];
|
|
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
doRemoveFromValueTree(value, segments);
|
|
if (Object.keys(value).length === 0) {
|
|
delete valueTree[first];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function getConfigurationValue(config, settingPath, defaultValue) {
|
|
function accessSetting(config, path) {
|
|
let current = config;
|
|
for (let i = 0; i < path.length; i++) { // tslint:disable-line
|
|
if (typeof current !== 'object' || current === null) {
|
|
return undefined;
|
|
}
|
|
current = current[path[i]];
|
|
}
|
|
return current;
|
|
}
|
|
const path = settingPath.split('.');
|
|
const result = accessSetting(config, path);
|
|
return typeof result === 'undefined' ? defaultValue : result;
|
|
}
|
|
exports.getConfigurationValue = getConfigurationValue;
|
|
function loadDefaultConfigurations() {
|
|
let file = path_1.default.join(pluginRoot, 'data/schema.json');
|
|
if (!fs_1.default.existsSync(file)) {
|
|
console.error('schema.json not found, reinstall coc.nvim to fix this!'); // tslint:disable-line
|
|
return { contents: {} };
|
|
}
|
|
let content = fs_1.default.readFileSync(file, 'utf8');
|
|
let { properties } = JSON.parse(content);
|
|
let config = {};
|
|
Object.keys(properties).forEach(key => {
|
|
let value = properties[key].default;
|
|
if (value !== undefined) {
|
|
addToValueTree(config, key, value, message => {
|
|
logger.error(message); // tslint:disable-line
|
|
});
|
|
}
|
|
});
|
|
return { contents: config };
|
|
}
|
|
exports.loadDefaultConfigurations = loadDefaultConfigurations;
|
|
function getKeys(obj, curr) {
|
|
let keys = [];
|
|
for (let key of Object.keys(obj)) {
|
|
let val = obj[key];
|
|
let newKey = curr ? `${curr}.${key}` : key;
|
|
keys.push(newKey);
|
|
if (is_1.objectLiteral(val)) {
|
|
keys.push(...getKeys(val, newKey));
|
|
}
|
|
}
|
|
return keys;
|
|
}
|
|
exports.getKeys = getKeys;
|
|
function getChangedKeys(from, to) {
|
|
let keys = [];
|
|
let fromKeys = getKeys(from);
|
|
let toKeys = getKeys(to);
|
|
const added = toKeys.filter(key => fromKeys.indexOf(key) === -1);
|
|
const removed = fromKeys.filter(key => toKeys.indexOf(key) === -1);
|
|
keys.push(...added);
|
|
keys.push(...removed);
|
|
for (const key of fromKeys) {
|
|
if (toKeys.indexOf(key) == -1)
|
|
continue;
|
|
const value1 = getConfigurationValue(from, key);
|
|
const value2 = getConfigurationValue(to, key);
|
|
if (!object_1.equals(value1, value2)) {
|
|
keys.push(key);
|
|
}
|
|
}
|
|
return keys;
|
|
}
|
|
exports.getChangedKeys = getChangedKeys;
|
|
//# sourceMappingURL=util.js.map
|
|
|
|
/***/ }),
|
|
/* 195 */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createScanner", function() { return createScanner; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocation", function() { return getLocation; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parse", function() { return parse; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parseTree", function() { return parseTree; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findNodeAtLocation", function() { return findNodeAtLocation; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findNodeAtOffset", function() { return findNodeAtOffset; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNodePath", function() { return getNodePath; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNodeValue", function() { return getNodeValue; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "visit", function() { return visit; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "stripComments", function() { return stripComments; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "printParseErrorCode", function() { return printParseErrorCode; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "format", function() { return format; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "modify", function() { return modify; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "applyEdits", function() { return applyEdits; });
|
|
/* harmony import */ var _impl_format__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196);
|
|
/* harmony import */ var _impl_edit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198);
|
|
/* harmony import */ var _impl_scanner__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(197);
|
|
/* harmony import */ var _impl_parser__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(199);
|
|
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Creates a JSON scanner on the given text.
|
|
* If ignoreTrivia is set, whitespaces or comments are ignored.
|
|
*/
|
|
var createScanner = _impl_scanner__WEBPACK_IMPORTED_MODULE_2__["createScanner"];
|
|
/**
|
|
* For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.
|
|
*/
|
|
var getLocation = _impl_parser__WEBPACK_IMPORTED_MODULE_3__["getLocation"];
|
|
/**
|
|
* Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.
|
|
* Therefore, always check the errors list to find out if the input was valid.
|
|
*/
|
|
var parse = _impl_parser__WEBPACK_IMPORTED_MODULE_3__["parse"];
|
|
/**
|
|
* Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.
|
|
*/
|
|
var parseTree = _impl_parser__WEBPACK_IMPORTED_MODULE_3__["parseTree"];
|
|
/**
|
|
* Finds the node at the given path in a JSON DOM.
|
|
*/
|
|
var findNodeAtLocation = _impl_parser__WEBPACK_IMPORTED_MODULE_3__["findNodeAtLocation"];
|
|
/**
|
|
* Finds the innermost node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.
|
|
*/
|
|
var findNodeAtOffset = _impl_parser__WEBPACK_IMPORTED_MODULE_3__["findNodeAtOffset"];
|
|
/**
|
|
* Gets the JSON path of the given JSON DOM node
|
|
*/
|
|
var getNodePath = _impl_parser__WEBPACK_IMPORTED_MODULE_3__["getNodePath"];
|
|
/**
|
|
* Evaluates the JavaScript object of the given JSON DOM node
|
|
*/
|
|
var getNodeValue = _impl_parser__WEBPACK_IMPORTED_MODULE_3__["getNodeValue"];
|
|
/**
|
|
* Parses the given text and invokes the visitor functions for each object, array and literal reached.
|
|
*/
|
|
var visit = _impl_parser__WEBPACK_IMPORTED_MODULE_3__["visit"];
|
|
/**
|
|
* Takes JSON with JavaScript-style comments and remove
|
|
* them. Optionally replaces every none-newline character
|
|
* of comments with a replaceCharacter
|
|
*/
|
|
var stripComments = _impl_parser__WEBPACK_IMPORTED_MODULE_3__["stripComments"];
|
|
function printParseErrorCode(code) {
|
|
switch (code) {
|
|
case 1 /* InvalidSymbol */: return 'InvalidSymbol';
|
|
case 2 /* InvalidNumberFormat */: return 'InvalidNumberFormat';
|
|
case 3 /* PropertyNameExpected */: return 'PropertyNameExpected';
|
|
case 4 /* ValueExpected */: return 'ValueExpected';
|
|
case 5 /* ColonExpected */: return 'ColonExpected';
|
|
case 6 /* CommaExpected */: return 'CommaExpected';
|
|
case 7 /* CloseBraceExpected */: return 'CloseBraceExpected';
|
|
case 8 /* CloseBracketExpected */: return 'CloseBracketExpected';
|
|
case 9 /* EndOfFileExpected */: return 'EndOfFileExpected';
|
|
case 10 /* InvalidCommentToken */: return 'InvalidCommentToken';
|
|
case 11 /* UnexpectedEndOfComment */: return 'UnexpectedEndOfComment';
|
|
case 12 /* UnexpectedEndOfString */: return 'UnexpectedEndOfString';
|
|
case 13 /* UnexpectedEndOfNumber */: return 'UnexpectedEndOfNumber';
|
|
case 14 /* InvalidUnicode */: return 'InvalidUnicode';
|
|
case 15 /* InvalidEscapeCharacter */: return 'InvalidEscapeCharacter';
|
|
case 16 /* InvalidCharacter */: return 'InvalidCharacter';
|
|
}
|
|
return '<unknown ParseErrorCode>';
|
|
}
|
|
/**
|
|
* Computes the edits needed to format a JSON document.
|
|
*
|
|
* @param documentText The input text
|
|
* @param range The range to format or `undefined` to format the full content
|
|
* @param options The formatting options
|
|
* @returns A list of edit operations describing the formatting changes to the original document. Edits can be either inserts, replacements or
|
|
* removals of text segments. All offsets refer to the original state of the document. No two edits must change or remove the same range of
|
|
* text in the original document. However, multiple edits can have
|
|
* the same offset, for example multiple inserts, or an insert followed by a remove or replace. The order in the array defines which edit is applied first.
|
|
* To apply edits to an input, you can use `applyEdits`.
|
|
*/
|
|
function format(documentText, range, options) {
|
|
return _impl_format__WEBPACK_IMPORTED_MODULE_0__["format"](documentText, range, options);
|
|
}
|
|
/**
|
|
* Computes the edits needed to modify a value in the JSON document.
|
|
*
|
|
* @param documentText The input text
|
|
* @param path The path of the value to change. The path represents either to the document root, a property or an array item.
|
|
* If the path points to an non-existing property or item, it will be created.
|
|
* @param value The new value for the specified property or item. If the value is undefined,
|
|
* the property or item will be removed.
|
|
* @param options Options
|
|
* @returns A list of edit operations describing the formatting changes to the original document. Edits can be either inserts, replacements or
|
|
* removals of text segments. All offsets refer to the original state of the document. No two edits must change or remove the same range of
|
|
* text in the original document. However, multiple edits can have
|
|
* the same offset, for example multiple inserts, or an insert followed by a remove or replace. The order in the array defines which edit is applied first.
|
|
* To apply edits to an input, you can use `applyEdits`.
|
|
*/
|
|
function modify(text, path, value, options) {
|
|
return _impl_edit__WEBPACK_IMPORTED_MODULE_1__["setProperty"](text, path, value, options.formattingOptions, options.getInsertionIndex);
|
|
}
|
|
/**
|
|
* Applies edits to a input string.
|
|
*/
|
|
function applyEdits(text, edits) {
|
|
for (var i = edits.length - 1; i >= 0; i--) {
|
|
text = _impl_edit__WEBPACK_IMPORTED_MODULE_1__["applyEdit"](text, edits[i]);
|
|
}
|
|
return text;
|
|
}
|
|
//# sourceMappingURL=main.js.map
|
|
|
|
/***/ }),
|
|
/* 196 */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "format", function() { return format; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isEOL", function() { return isEOL; });
|
|
/* harmony import */ var _scanner__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(197);
|
|
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
|
|
function format(documentText, range, options) {
|
|
var initialIndentLevel;
|
|
var formatText;
|
|
var formatTextStart;
|
|
var rangeStart;
|
|
var rangeEnd;
|
|
if (range) {
|
|
rangeStart = range.offset;
|
|
rangeEnd = rangeStart + range.length;
|
|
formatTextStart = rangeStart;
|
|
while (formatTextStart > 0 && !isEOL(documentText, formatTextStart - 1)) {
|
|
formatTextStart--;
|
|
}
|
|
var endOffset = rangeEnd;
|
|
while (endOffset < documentText.length && !isEOL(documentText, endOffset)) {
|
|
endOffset++;
|
|
}
|
|
formatText = documentText.substring(formatTextStart, endOffset);
|
|
initialIndentLevel = computeIndentLevel(formatText, options);
|
|
}
|
|
else {
|
|
formatText = documentText;
|
|
initialIndentLevel = 0;
|
|
formatTextStart = 0;
|
|
rangeStart = 0;
|
|
rangeEnd = documentText.length;
|
|
}
|
|
var eol = getEOL(options, documentText);
|
|
var lineBreak = false;
|
|
var indentLevel = 0;
|
|
var indentValue;
|
|
if (options.insertSpaces) {
|
|
indentValue = repeat(' ', options.tabSize || 4);
|
|
}
|
|
else {
|
|
indentValue = '\t';
|
|
}
|
|
var scanner = Object(_scanner__WEBPACK_IMPORTED_MODULE_0__["createScanner"])(formatText, false);
|
|
var hasError = false;
|
|
function newLineAndIndent() {
|
|
return eol + repeat(indentValue, initialIndentLevel + indentLevel);
|
|
}
|
|
function scanNext() {
|
|
var token = scanner.scan();
|
|
lineBreak = false;
|
|
while (token === 15 /* Trivia */ || token === 14 /* LineBreakTrivia */) {
|
|
lineBreak = lineBreak || (token === 14 /* LineBreakTrivia */);
|
|
token = scanner.scan();
|
|
}
|
|
hasError = token === 16 /* Unknown */ || scanner.getTokenError() !== 0 /* None */;
|
|
return token;
|
|
}
|
|
var editOperations = [];
|
|
function addEdit(text, startOffset, endOffset) {
|
|
if (!hasError && startOffset < rangeEnd && endOffset > rangeStart && documentText.substring(startOffset, endOffset) !== text) {
|
|
editOperations.push({ offset: startOffset, length: endOffset - startOffset, content: text });
|
|
}
|
|
}
|
|
var firstToken = scanNext();
|
|
if (firstToken !== 17 /* EOF */) {
|
|
var firstTokenStart = scanner.getTokenOffset() + formatTextStart;
|
|
var initialIndent = repeat(indentValue, initialIndentLevel);
|
|
addEdit(initialIndent, formatTextStart, firstTokenStart);
|
|
}
|
|
while (firstToken !== 17 /* EOF */) {
|
|
var firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
|
|
var secondToken = scanNext();
|
|
var replaceContent = '';
|
|
while (!lineBreak && (secondToken === 12 /* LineCommentTrivia */ || secondToken === 13 /* BlockCommentTrivia */)) {
|
|
// comments on the same line: keep them on the same line, but ignore them otherwise
|
|
var commentTokenStart = scanner.getTokenOffset() + formatTextStart;
|
|
addEdit(' ', firstTokenEnd, commentTokenStart);
|
|
firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
|
|
replaceContent = secondToken === 12 /* LineCommentTrivia */ ? newLineAndIndent() : '';
|
|
secondToken = scanNext();
|
|
}
|
|
if (secondToken === 2 /* CloseBraceToken */) {
|
|
if (firstToken !== 1 /* OpenBraceToken */) {
|
|
indentLevel--;
|
|
replaceContent = newLineAndIndent();
|
|
}
|
|
}
|
|
else if (secondToken === 4 /* CloseBracketToken */) {
|
|
if (firstToken !== 3 /* OpenBracketToken */) {
|
|
indentLevel--;
|
|
replaceContent = newLineAndIndent();
|
|
}
|
|
}
|
|
else {
|
|
switch (firstToken) {
|
|
case 3 /* OpenBracketToken */:
|
|
case 1 /* OpenBraceToken */:
|
|
indentLevel++;
|
|
replaceContent = newLineAndIndent();
|
|
break;
|
|
case 5 /* CommaToken */:
|
|
case 12 /* LineCommentTrivia */:
|
|
replaceContent = newLineAndIndent();
|
|
break;
|
|
case 13 /* BlockCommentTrivia */:
|
|
if (lineBreak) {
|
|
replaceContent = newLineAndIndent();
|
|
}
|
|
else {
|
|
// symbol following comment on the same line: keep on same line, separate with ' '
|
|
replaceContent = ' ';
|
|
}
|
|
break;
|
|
case 6 /* ColonToken */:
|
|
replaceContent = ' ';
|
|
break;
|
|
case 10 /* StringLiteral */:
|
|
if (secondToken === 6 /* ColonToken */) {
|
|
replaceContent = '';
|
|
break;
|
|
}
|
|
// fall through
|
|
case 7 /* NullKeyword */:
|
|
case 8 /* TrueKeyword */:
|
|
case 9 /* FalseKeyword */:
|
|
case 11 /* NumericLiteral */:
|
|
case 2 /* CloseBraceToken */:
|
|
case 4 /* CloseBracketToken */:
|
|
if (secondToken === 12 /* LineCommentTrivia */ || secondToken === 13 /* BlockCommentTrivia */) {
|
|
replaceContent = ' ';
|
|
}
|
|
else if (secondToken !== 5 /* CommaToken */ && secondToken !== 17 /* EOF */) {
|
|
hasError = true;
|
|
}
|
|
break;
|
|
case 16 /* Unknown */:
|
|
hasError = true;
|
|
break;
|
|
}
|
|
if (lineBreak && (secondToken === 12 /* LineCommentTrivia */ || secondToken === 13 /* BlockCommentTrivia */)) {
|
|
replaceContent = newLineAndIndent();
|
|
}
|
|
}
|
|
var secondTokenStart = scanner.getTokenOffset() + formatTextStart;
|
|
addEdit(replaceContent, firstTokenEnd, secondTokenStart);
|
|
firstToken = secondToken;
|
|
}
|
|
return editOperations;
|
|
}
|
|
function repeat(s, count) {
|
|
var result = '';
|
|
for (var i = 0; i < count; i++) {
|
|
result += s;
|
|
}
|
|
return result;
|
|
}
|
|
function computeIndentLevel(content, options) {
|
|
var i = 0;
|
|
var nChars = 0;
|
|
var tabSize = options.tabSize || 4;
|
|
while (i < content.length) {
|
|
var ch = content.charAt(i);
|
|
if (ch === ' ') {
|
|
nChars++;
|
|
}
|
|
else if (ch === '\t') {
|
|
nChars += tabSize;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
return Math.floor(nChars / tabSize);
|
|
}
|
|
function getEOL(options, text) {
|
|
for (var i = 0; i < text.length; i++) {
|
|
var ch = text.charAt(i);
|
|
if (ch === '\r') {
|
|
if (i + 1 < text.length && text.charAt(i + 1) === '\n') {
|
|
return '\r\n';
|
|
}
|
|
return '\r';
|
|
}
|
|
else if (ch === '\n') {
|
|
return '\n';
|
|
}
|
|
}
|
|
return (options && options.eol) || '\n';
|
|
}
|
|
function isEOL(text, offset) {
|
|
return '\r\n'.indexOf(text.charAt(offset)) !== -1;
|
|
}
|
|
//# sourceMappingURL=format.js.map
|
|
|
|
/***/ }),
|
|
/* 197 */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createScanner", function() { return createScanner; });
|
|
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates a JSON scanner on the given text.
|
|
* If ignoreTrivia is set, whitespaces or comments are ignored.
|
|
*/
|
|
function createScanner(text, ignoreTrivia) {
|
|
if (ignoreTrivia === void 0) { ignoreTrivia = false; }
|
|
var pos = 0, len = text.length, value = '', tokenOffset = 0, token = 16 /* Unknown */, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0 /* None */;
|
|
function scanHexDigits(count, exact) {
|
|
var digits = 0;
|
|
var value = 0;
|
|
while (digits < count || !exact) {
|
|
var ch = text.charCodeAt(pos);
|
|
if (ch >= 48 /* _0 */ && ch <= 57 /* _9 */) {
|
|
value = value * 16 + ch - 48 /* _0 */;
|
|
}
|
|
else if (ch >= 65 /* A */ && ch <= 70 /* F */) {
|
|
value = value * 16 + ch - 65 /* A */ + 10;
|
|
}
|
|
else if (ch >= 97 /* a */ && ch <= 102 /* f */) {
|
|
value = value * 16 + ch - 97 /* a */ + 10;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
pos++;
|
|
digits++;
|
|
}
|
|
if (digits < count) {
|
|
value = -1;
|
|
}
|
|
return value;
|
|
}
|
|
function setPosition(newPosition) {
|
|
pos = newPosition;
|
|
value = '';
|
|
tokenOffset = 0;
|
|
token = 16 /* Unknown */;
|
|
scanError = 0 /* None */;
|
|
}
|
|
function scanNumber() {
|
|
var start = pos;
|
|
if (text.charCodeAt(pos) === 48 /* _0 */) {
|
|
pos++;
|
|
}
|
|
else {
|
|
pos++;
|
|
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
pos++;
|
|
}
|
|
}
|
|
if (pos < text.length && text.charCodeAt(pos) === 46 /* dot */) {
|
|
pos++;
|
|
if (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
pos++;
|
|
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
pos++;
|
|
}
|
|
}
|
|
else {
|
|
scanError = 3 /* UnexpectedEndOfNumber */;
|
|
return text.substring(start, pos);
|
|
}
|
|
}
|
|
var end = pos;
|
|
if (pos < text.length && (text.charCodeAt(pos) === 69 /* E */ || text.charCodeAt(pos) === 101 /* e */)) {
|
|
pos++;
|
|
if (pos < text.length && text.charCodeAt(pos) === 43 /* plus */ || text.charCodeAt(pos) === 45 /* minus */) {
|
|
pos++;
|
|
}
|
|
if (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
pos++;
|
|
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
pos++;
|
|
}
|
|
end = pos;
|
|
}
|
|
else {
|
|
scanError = 3 /* UnexpectedEndOfNumber */;
|
|
}
|
|
}
|
|
return text.substring(start, end);
|
|
}
|
|
function scanString() {
|
|
var result = '', start = pos;
|
|
while (true) {
|
|
if (pos >= len) {
|
|
result += text.substring(start, pos);
|
|
scanError = 2 /* UnexpectedEndOfString */;
|
|
break;
|
|
}
|
|
var ch = text.charCodeAt(pos);
|
|
if (ch === 34 /* doubleQuote */) {
|
|
result += text.substring(start, pos);
|
|
pos++;
|
|
break;
|
|
}
|
|
if (ch === 92 /* backslash */) {
|
|
result += text.substring(start, pos);
|
|
pos++;
|
|
if (pos >= len) {
|
|
scanError = 2 /* UnexpectedEndOfString */;
|
|
break;
|
|
}
|
|
ch = text.charCodeAt(pos++);
|
|
switch (ch) {
|
|
case 34 /* doubleQuote */:
|
|
result += '\"';
|
|
break;
|
|
case 92 /* backslash */:
|
|
result += '\\';
|
|
break;
|
|
case 47 /* slash */:
|
|
result += '/';
|
|
break;
|
|
case 98 /* b */:
|
|
result += '\b';
|
|
break;
|
|
case 102 /* f */:
|
|
result += '\f';
|
|
break;
|
|
case 110 /* n */:
|
|
result += '\n';
|
|
break;
|
|
case 114 /* r */:
|
|
result += '\r';
|
|
break;
|
|
case 116 /* t */:
|
|
result += '\t';
|
|
break;
|
|
case 117 /* u */:
|
|
var ch_1 = scanHexDigits(4, true);
|
|
if (ch_1 >= 0) {
|
|
result += String.fromCharCode(ch_1);
|
|
}
|
|
else {
|
|
scanError = 4 /* InvalidUnicode */;
|
|
}
|
|
break;
|
|
default:
|
|
scanError = 5 /* InvalidEscapeCharacter */;
|
|
}
|
|
start = pos;
|
|
continue;
|
|
}
|
|
if (ch >= 0 && ch <= 0x1f) {
|
|
if (isLineBreak(ch)) {
|
|
result += text.substring(start, pos);
|
|
scanError = 2 /* UnexpectedEndOfString */;
|
|
break;
|
|
}
|
|
else {
|
|
scanError = 6 /* InvalidCharacter */;
|
|
// mark as error but continue with string
|
|
}
|
|
}
|
|
pos++;
|
|
}
|
|
return result;
|
|
}
|
|
function scanNext() {
|
|
value = '';
|
|
scanError = 0 /* None */;
|
|
tokenOffset = pos;
|
|
lineStartOffset = lineNumber;
|
|
prevTokenLineStartOffset = tokenLineStartOffset;
|
|
if (pos >= len) {
|
|
// at the end
|
|
tokenOffset = len;
|
|
return token = 17 /* EOF */;
|
|
}
|
|
var code = text.charCodeAt(pos);
|
|
// trivia: whitespace
|
|
if (isWhiteSpace(code)) {
|
|
do {
|
|
pos++;
|
|
value += String.fromCharCode(code);
|
|
code = text.charCodeAt(pos);
|
|
} while (isWhiteSpace(code));
|
|
return token = 15 /* Trivia */;
|
|
}
|
|
// trivia: newlines
|
|
if (isLineBreak(code)) {
|
|
pos++;
|
|
value += String.fromCharCode(code);
|
|
if (code === 13 /* carriageReturn */ && text.charCodeAt(pos) === 10 /* lineFeed */) {
|
|
pos++;
|
|
value += '\n';
|
|
}
|
|
lineNumber++;
|
|
tokenLineStartOffset = pos;
|
|
return token = 14 /* LineBreakTrivia */;
|
|
}
|
|
switch (code) {
|
|
// tokens: []{}:,
|
|
case 123 /* openBrace */:
|
|
pos++;
|
|
return token = 1 /* OpenBraceToken */;
|
|
case 125 /* closeBrace */:
|
|
pos++;
|
|
return token = 2 /* CloseBraceToken */;
|
|
case 91 /* openBracket */:
|
|
pos++;
|
|
return token = 3 /* OpenBracketToken */;
|
|
case 93 /* closeBracket */:
|
|
pos++;
|
|
return token = 4 /* CloseBracketToken */;
|
|
case 58 /* colon */:
|
|
pos++;
|
|
return token = 6 /* ColonToken */;
|
|
case 44 /* comma */:
|
|
pos++;
|
|
return token = 5 /* CommaToken */;
|
|
// strings
|
|
case 34 /* doubleQuote */:
|
|
pos++;
|
|
value = scanString();
|
|
return token = 10 /* StringLiteral */;
|
|
// comments
|
|
case 47 /* slash */:
|
|
var start = pos - 1;
|
|
// Single-line comment
|
|
if (text.charCodeAt(pos + 1) === 47 /* slash */) {
|
|
pos += 2;
|
|
while (pos < len) {
|
|
if (isLineBreak(text.charCodeAt(pos))) {
|
|
break;
|
|
}
|
|
pos++;
|
|
}
|
|
value = text.substring(start, pos);
|
|
return token = 12 /* LineCommentTrivia */;
|
|
}
|
|
// Multi-line comment
|
|
if (text.charCodeAt(pos + 1) === 42 /* asterisk */) {
|
|
pos += 2;
|
|
var safeLength = len - 1; // For lookahead.
|
|
var commentClosed = false;
|
|
while (pos < safeLength) {
|
|
var ch = text.charCodeAt(pos);
|
|
if (ch === 42 /* asterisk */ && text.charCodeAt(pos + 1) === 47 /* slash */) {
|
|
pos += 2;
|
|
commentClosed = true;
|
|
break;
|
|
}
|
|
pos++;
|
|
if (isLineBreak(ch)) {
|
|
if (ch === 13 /* carriageReturn */ && text.charCodeAt(pos) === 10 /* lineFeed */) {
|
|
pos++;
|
|
}
|
|
lineNumber++;
|
|
tokenLineStartOffset = pos;
|
|
}
|
|
}
|
|
if (!commentClosed) {
|
|
pos++;
|
|
scanError = 1 /* UnexpectedEndOfComment */;
|
|
}
|
|
value = text.substring(start, pos);
|
|
return token = 13 /* BlockCommentTrivia */;
|
|
}
|
|
// just a single slash
|
|
value += String.fromCharCode(code);
|
|
pos++;
|
|
return token = 16 /* Unknown */;
|
|
// numbers
|
|
case 45 /* minus */:
|
|
value += String.fromCharCode(code);
|
|
pos++;
|
|
if (pos === len || !isDigit(text.charCodeAt(pos))) {
|
|
return token = 16 /* Unknown */;
|
|
}
|
|
// found a minus, followed by a number so
|
|
// we fall through to proceed with scanning
|
|
// numbers
|
|
case 48 /* _0 */:
|
|
case 49 /* _1 */:
|
|
case 50 /* _2 */:
|
|
case 51 /* _3 */:
|
|
case 52 /* _4 */:
|
|
case 53 /* _5 */:
|
|
case 54 /* _6 */:
|
|
case 55 /* _7 */:
|
|
case 56 /* _8 */:
|
|
case 57 /* _9 */:
|
|
value += scanNumber();
|
|
return token = 11 /* NumericLiteral */;
|
|
// literals and unknown symbols
|
|
default:
|
|
// is a literal? Read the full word.
|
|
while (pos < len && isUnknownContentCharacter(code)) {
|
|
pos++;
|
|
code = text.charCodeAt(pos);
|
|
}
|
|
if (tokenOffset !== pos) {
|
|
value = text.substring(tokenOffset, pos);
|
|
// keywords: true, false, null
|
|
switch (value) {
|
|
case 'true': return token = 8 /* TrueKeyword */;
|
|
case 'false': return token = 9 /* FalseKeyword */;
|
|
case 'null': return token = 7 /* NullKeyword */;
|
|
}
|
|
return token = 16 /* Unknown */;
|
|
}
|
|
// some
|
|
value += String.fromCharCode(code);
|
|
pos++;
|
|
return token = 16 /* Unknown */;
|
|
}
|
|
}
|
|
function isUnknownContentCharacter(code) {
|
|
if (isWhiteSpace(code) || isLineBreak(code)) {
|
|
return false;
|
|
}
|
|
switch (code) {
|
|
case 125 /* closeBrace */:
|
|
case 93 /* closeBracket */:
|
|
case 123 /* openBrace */:
|
|
case 91 /* openBracket */:
|
|
case 34 /* doubleQuote */:
|
|
case 58 /* colon */:
|
|
case 44 /* comma */:
|
|
case 47 /* slash */:
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
function scanNextNonTrivia() {
|
|
var result;
|
|
do {
|
|
result = scanNext();
|
|
} while (result >= 12 /* LineCommentTrivia */ && result <= 15 /* Trivia */);
|
|
return result;
|
|
}
|
|
return {
|
|
setPosition: setPosition,
|
|
getPosition: function () { return pos; },
|
|
scan: ignoreTrivia ? scanNextNonTrivia : scanNext,
|
|
getToken: function () { return token; },
|
|
getTokenValue: function () { return value; },
|
|
getTokenOffset: function () { return tokenOffset; },
|
|
getTokenLength: function () { return pos - tokenOffset; },
|
|
getTokenStartLine: function () { return lineStartOffset; },
|
|
getTokenStartCharacter: function () { return tokenOffset - prevTokenLineStartOffset; },
|
|
getTokenError: function () { return scanError; },
|
|
};
|
|
}
|
|
function isWhiteSpace(ch) {
|
|
return ch === 32 /* space */ || ch === 9 /* tab */ || ch === 11 /* verticalTab */ || ch === 12 /* formFeed */ ||
|
|
ch === 160 /* nonBreakingSpace */ || ch === 5760 /* ogham */ || ch >= 8192 /* enQuad */ && ch <= 8203 /* zeroWidthSpace */ ||
|
|
ch === 8239 /* narrowNoBreakSpace */ || ch === 8287 /* mathematicalSpace */ || ch === 12288 /* ideographicSpace */ || ch === 65279 /* byteOrderMark */;
|
|
}
|
|
function isLineBreak(ch) {
|
|
return ch === 10 /* lineFeed */ || ch === 13 /* carriageReturn */ || ch === 8232 /* lineSeparator */ || ch === 8233 /* paragraphSeparator */;
|
|
}
|
|
function isDigit(ch) {
|
|
return ch >= 48 /* _0 */ && ch <= 57 /* _9 */;
|
|
}
|
|
//# sourceMappingURL=scanner.js.map
|
|
|
|
/***/ }),
|
|
/* 198 */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeProperty", function() { return removeProperty; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "setProperty", function() { return setProperty; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "applyEdit", function() { return applyEdit; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isWS", function() { return isWS; });
|
|
/* harmony import */ var _format__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196);
|
|
/* harmony import */ var _parser__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(199);
|
|
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
function removeProperty(text, path, formattingOptions) {
|
|
return setProperty(text, path, void 0, formattingOptions);
|
|
}
|
|
function setProperty(text, originalPath, value, formattingOptions, getInsertionIndex) {
|
|
var _a;
|
|
var path = originalPath.slice();
|
|
var errors = [];
|
|
var root = Object(_parser__WEBPACK_IMPORTED_MODULE_1__["parseTree"])(text, errors);
|
|
var parent = void 0;
|
|
var lastSegment = void 0;
|
|
while (path.length > 0) {
|
|
lastSegment = path.pop();
|
|
parent = Object(_parser__WEBPACK_IMPORTED_MODULE_1__["findNodeAtLocation"])(root, path);
|
|
if (parent === void 0 && value !== void 0) {
|
|
if (typeof lastSegment === 'string') {
|
|
value = (_a = {}, _a[lastSegment] = value, _a);
|
|
}
|
|
else {
|
|
value = [value];
|
|
}
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
if (!parent) {
|
|
// empty document
|
|
if (value === void 0) { // delete
|
|
throw new Error('Can not delete in empty document');
|
|
}
|
|
return withFormatting(text, { offset: root ? root.offset : 0, length: root ? root.length : 0, content: JSON.stringify(value) }, formattingOptions);
|
|
}
|
|
else if (parent.type === 'object' && typeof lastSegment === 'string' && Array.isArray(parent.children)) {
|
|
var existing = Object(_parser__WEBPACK_IMPORTED_MODULE_1__["findNodeAtLocation"])(parent, [lastSegment]);
|
|
if (existing !== void 0) {
|
|
if (value === void 0) { // delete
|
|
if (!existing.parent) {
|
|
throw new Error('Malformed AST');
|
|
}
|
|
var propertyIndex = parent.children.indexOf(existing.parent);
|
|
var removeBegin = void 0;
|
|
var removeEnd = existing.parent.offset + existing.parent.length;
|
|
if (propertyIndex > 0) {
|
|
// remove the comma of the previous node
|
|
var previous = parent.children[propertyIndex - 1];
|
|
removeBegin = previous.offset + previous.length;
|
|
}
|
|
else {
|
|
removeBegin = parent.offset + 1;
|
|
if (parent.children.length > 1) {
|
|
// remove the comma of the next node
|
|
var next = parent.children[1];
|
|
removeEnd = next.offset;
|
|
}
|
|
}
|
|
return withFormatting(text, { offset: removeBegin, length: removeEnd - removeBegin, content: '' }, formattingOptions);
|
|
}
|
|
else {
|
|
// set value of existing property
|
|
return withFormatting(text, { offset: existing.offset, length: existing.length, content: JSON.stringify(value) }, formattingOptions);
|
|
}
|
|
}
|
|
else {
|
|
if (value === void 0) { // delete
|
|
return []; // property does not exist, nothing to do
|
|
}
|
|
var newProperty = JSON.stringify(lastSegment) + ": " + JSON.stringify(value);
|
|
var index = getInsertionIndex ? getInsertionIndex(parent.children.map(function (p) { return p.children[0].value; })) : parent.children.length;
|
|
var edit = void 0;
|
|
if (index > 0) {
|
|
var previous = parent.children[index - 1];
|
|
edit = { offset: previous.offset + previous.length, length: 0, content: ',' + newProperty };
|
|
}
|
|
else if (parent.children.length === 0) {
|
|
edit = { offset: parent.offset + 1, length: 0, content: newProperty };
|
|
}
|
|
else {
|
|
edit = { offset: parent.offset + 1, length: 0, content: newProperty + ',' };
|
|
}
|
|
return withFormatting(text, edit, formattingOptions);
|
|
}
|
|
}
|
|
else if (parent.type === 'array' && typeof lastSegment === 'number' && Array.isArray(parent.children)) {
|
|
var insertIndex = lastSegment;
|
|
if (insertIndex === -1) {
|
|
// Insert
|
|
var newProperty = "" + JSON.stringify(value);
|
|
var edit = void 0;
|
|
if (parent.children.length === 0) {
|
|
edit = { offset: parent.offset + 1, length: 0, content: newProperty };
|
|
}
|
|
else {
|
|
var previous = parent.children[parent.children.length - 1];
|
|
edit = { offset: previous.offset + previous.length, length: 0, content: ',' + newProperty };
|
|
}
|
|
return withFormatting(text, edit, formattingOptions);
|
|
}
|
|
else {
|
|
if (value === void 0 && parent.children.length >= 0) {
|
|
//Removal
|
|
var removalIndex = lastSegment;
|
|
var toRemove = parent.children[removalIndex];
|
|
var edit = void 0;
|
|
if (parent.children.length === 1) {
|
|
// only item
|
|
edit = { offset: parent.offset + 1, length: parent.length - 2, content: '' };
|
|
}
|
|
else if (parent.children.length - 1 === removalIndex) {
|
|
// last item
|
|
var previous = parent.children[removalIndex - 1];
|
|
var offset = previous.offset + previous.length;
|
|
var parentEndOffset = parent.offset + parent.length;
|
|
edit = { offset: offset, length: parentEndOffset - 2 - offset, content: '' };
|
|
}
|
|
else {
|
|
edit = { offset: toRemove.offset, length: parent.children[removalIndex + 1].offset - toRemove.offset, content: '' };
|
|
}
|
|
return withFormatting(text, edit, formattingOptions);
|
|
}
|
|
else {
|
|
throw new Error('Array modification not supported yet');
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
throw new Error("Can not add " + (typeof lastSegment !== 'number' ? 'index' : 'property') + " to parent of type " + parent.type);
|
|
}
|
|
}
|
|
function withFormatting(text, edit, formattingOptions) {
|
|
// apply the edit
|
|
var newText = applyEdit(text, edit);
|
|
// format the new text
|
|
var begin = edit.offset;
|
|
var end = edit.offset + edit.content.length;
|
|
if (edit.length === 0 || edit.content.length === 0) { // insert or remove
|
|
while (begin > 0 && !Object(_format__WEBPACK_IMPORTED_MODULE_0__["isEOL"])(newText, begin - 1)) {
|
|
begin--;
|
|
}
|
|
while (end < newText.length && !Object(_format__WEBPACK_IMPORTED_MODULE_0__["isEOL"])(newText, end)) {
|
|
end++;
|
|
}
|
|
}
|
|
var edits = Object(_format__WEBPACK_IMPORTED_MODULE_0__["format"])(newText, { offset: begin, length: end - begin }, formattingOptions);
|
|
// apply the formatting edits and track the begin and end offsets of the changes
|
|
for (var i = edits.length - 1; i >= 0; i--) {
|
|
var edit_1 = edits[i];
|
|
newText = applyEdit(newText, edit_1);
|
|
begin = Math.min(begin, edit_1.offset);
|
|
end = Math.max(end, edit_1.offset + edit_1.length);
|
|
end += edit_1.content.length - edit_1.length;
|
|
}
|
|
// create a single edit with all changes
|
|
var editLength = text.length - (newText.length - end) - begin;
|
|
return [{ offset: begin, length: editLength, content: newText.substring(begin, end) }];
|
|
}
|
|
function applyEdit(text, edit) {
|
|
return text.substring(0, edit.offset) + edit.content + text.substring(edit.offset + edit.length);
|
|
}
|
|
function isWS(text, offset) {
|
|
return '\r\n \t'.indexOf(text.charAt(offset)) !== -1;
|
|
}
|
|
//# sourceMappingURL=edit.js.map
|
|
|
|
/***/ }),
|
|
/* 199 */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocation", function() { return getLocation; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parse", function() { return parse; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parseTree", function() { return parseTree; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findNodeAtLocation", function() { return findNodeAtLocation; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNodePath", function() { return getNodePath; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNodeValue", function() { return getNodeValue; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "contains", function() { return contains; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findNodeAtOffset", function() { return findNodeAtOffset; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "visit", function() { return visit; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "stripComments", function() { return stripComments; });
|
|
/* harmony import */ var _scanner__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(197);
|
|
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
|
|
var ParseOptions;
|
|
(function (ParseOptions) {
|
|
ParseOptions.DEFAULT = {
|
|
allowTrailingComma: false
|
|
};
|
|
})(ParseOptions || (ParseOptions = {}));
|
|
/**
|
|
* For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.
|
|
*/
|
|
function getLocation(text, position) {
|
|
var segments = []; // strings or numbers
|
|
var earlyReturnException = new Object();
|
|
var previousNode = void 0;
|
|
var previousNodeInst = {
|
|
value: {},
|
|
offset: 0,
|
|
length: 0,
|
|
type: 'object',
|
|
parent: void 0
|
|
};
|
|
var isAtPropertyKey = false;
|
|
function setPreviousNode(value, offset, length, type) {
|
|
previousNodeInst.value = value;
|
|
previousNodeInst.offset = offset;
|
|
previousNodeInst.length = length;
|
|
previousNodeInst.type = type;
|
|
previousNodeInst.colonOffset = void 0;
|
|
previousNode = previousNodeInst;
|
|
}
|
|
try {
|
|
visit(text, {
|
|
onObjectBegin: function (offset, length) {
|
|
if (position <= offset) {
|
|
throw earlyReturnException;
|
|
}
|
|
previousNode = void 0;
|
|
isAtPropertyKey = position > offset;
|
|
segments.push(''); // push a placeholder (will be replaced)
|
|
},
|
|
onObjectProperty: function (name, offset, length) {
|
|
if (position < offset) {
|
|
throw earlyReturnException;
|
|
}
|
|
setPreviousNode(name, offset, length, 'property');
|
|
segments[segments.length - 1] = name;
|
|
if (position <= offset + length) {
|
|
throw earlyReturnException;
|
|
}
|
|
},
|
|
onObjectEnd: function (offset, length) {
|
|
if (position <= offset) {
|
|
throw earlyReturnException;
|
|
}
|
|
previousNode = void 0;
|
|
segments.pop();
|
|
},
|
|
onArrayBegin: function (offset, length) {
|
|
if (position <= offset) {
|
|
throw earlyReturnException;
|
|
}
|
|
previousNode = void 0;
|
|
segments.push(0);
|
|
},
|
|
onArrayEnd: function (offset, length) {
|
|
if (position <= offset) {
|
|
throw earlyReturnException;
|
|
}
|
|
previousNode = void 0;
|
|
segments.pop();
|
|
},
|
|
onLiteralValue: function (value, offset, length) {
|
|
if (position < offset) {
|
|
throw earlyReturnException;
|
|
}
|
|
setPreviousNode(value, offset, length, getLiteralNodeType(value));
|
|
if (position <= offset + length) {
|
|
throw earlyReturnException;
|
|
}
|
|
},
|
|
onSeparator: function (sep, offset, length) {
|
|
if (position <= offset) {
|
|
throw earlyReturnException;
|
|
}
|
|
if (sep === ':' && previousNode && previousNode.type === 'property') {
|
|
previousNode.colonOffset = offset;
|
|
isAtPropertyKey = false;
|
|
previousNode = void 0;
|
|
}
|
|
else if (sep === ',') {
|
|
var last = segments[segments.length - 1];
|
|
if (typeof last === 'number') {
|
|
segments[segments.length - 1] = last + 1;
|
|
}
|
|
else {
|
|
isAtPropertyKey = true;
|
|
segments[segments.length - 1] = '';
|
|
}
|
|
previousNode = void 0;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
catch (e) {
|
|
if (e !== earlyReturnException) {
|
|
throw e;
|
|
}
|
|
}
|
|
return {
|
|
path: segments,
|
|
previousNode: previousNode,
|
|
isAtPropertyKey: isAtPropertyKey,
|
|
matches: function (pattern) {
|
|
var k = 0;
|
|
for (var i = 0; k < pattern.length && i < segments.length; i++) {
|
|
if (pattern[k] === segments[i] || pattern[k] === '*') {
|
|
k++;
|
|
}
|
|
else if (pattern[k] !== '**') {
|
|
return false;
|
|
}
|
|
}
|
|
return k === pattern.length;
|
|
}
|
|
};
|
|
}
|
|
/**
|
|
* Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.
|
|
* Therefore always check the errors list to find out if the input was valid.
|
|
*/
|
|
function parse(text, errors, options) {
|
|
if (errors === void 0) { errors = []; }
|
|
if (options === void 0) { options = ParseOptions.DEFAULT; }
|
|
var currentProperty = null;
|
|
var currentParent = [];
|
|
var previousParents = [];
|
|
function onValue(value) {
|
|
if (Array.isArray(currentParent)) {
|
|
currentParent.push(value);
|
|
}
|
|
else if (currentProperty) {
|
|
currentParent[currentProperty] = value;
|
|
}
|
|
}
|
|
var visitor = {
|
|
onObjectBegin: function () {
|
|
var object = {};
|
|
onValue(object);
|
|
previousParents.push(currentParent);
|
|
currentParent = object;
|
|
currentProperty = null;
|
|
},
|
|
onObjectProperty: function (name) {
|
|
currentProperty = name;
|
|
},
|
|
onObjectEnd: function () {
|
|
currentParent = previousParents.pop();
|
|
},
|
|
onArrayBegin: function () {
|
|
var array = [];
|
|
onValue(array);
|
|
previousParents.push(currentParent);
|
|
currentParent = array;
|
|
currentProperty = null;
|
|
},
|
|
onArrayEnd: function () {
|
|
currentParent = previousParents.pop();
|
|
},
|
|
onLiteralValue: onValue,
|
|
onError: function (error, offset, length) {
|
|
errors.push({ error: error, offset: offset, length: length });
|
|
}
|
|
};
|
|
visit(text, visitor, options);
|
|
return currentParent[0];
|
|
}
|
|
/**
|
|
* Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.
|
|
*/
|
|
function parseTree(text, errors, options) {
|
|
if (errors === void 0) { errors = []; }
|
|
if (options === void 0) { options = ParseOptions.DEFAULT; }
|
|
var currentParent = { type: 'array', offset: -1, length: -1, children: [], parent: void 0 }; // artificial root
|
|
function ensurePropertyComplete(endOffset) {
|
|
if (currentParent.type === 'property') {
|
|
currentParent.length = endOffset - currentParent.offset;
|
|
currentParent = currentParent.parent;
|
|
}
|
|
}
|
|
function onValue(valueNode) {
|
|
currentParent.children.push(valueNode);
|
|
return valueNode;
|
|
}
|
|
var visitor = {
|
|
onObjectBegin: function (offset) {
|
|
currentParent = onValue({ type: 'object', offset: offset, length: -1, parent: currentParent, children: [] });
|
|
},
|
|
onObjectProperty: function (name, offset, length) {
|
|
currentParent = onValue({ type: 'property', offset: offset, length: -1, parent: currentParent, children: [] });
|
|
currentParent.children.push({ type: 'string', value: name, offset: offset, length: length, parent: currentParent });
|
|
},
|
|
onObjectEnd: function (offset, length) {
|
|
currentParent.length = offset + length - currentParent.offset;
|
|
currentParent = currentParent.parent;
|
|
ensurePropertyComplete(offset + length);
|
|
},
|
|
onArrayBegin: function (offset, length) {
|
|
currentParent = onValue({ type: 'array', offset: offset, length: -1, parent: currentParent, children: [] });
|
|
},
|
|
onArrayEnd: function (offset, length) {
|
|
currentParent.length = offset + length - currentParent.offset;
|
|
currentParent = currentParent.parent;
|
|
ensurePropertyComplete(offset + length);
|
|
},
|
|
onLiteralValue: function (value, offset, length) {
|
|
onValue({ type: getLiteralNodeType(value), offset: offset, length: length, parent: currentParent, value: value });
|
|
ensurePropertyComplete(offset + length);
|
|
},
|
|
onSeparator: function (sep, offset, length) {
|
|
if (currentParent.type === 'property') {
|
|
if (sep === ':') {
|
|
currentParent.colonOffset = offset;
|
|
}
|
|
else if (sep === ',') {
|
|
ensurePropertyComplete(offset);
|
|
}
|
|
}
|
|
},
|
|
onError: function (error, offset, length) {
|
|
errors.push({ error: error, offset: offset, length: length });
|
|
}
|
|
};
|
|
visit(text, visitor, options);
|
|
var result = currentParent.children[0];
|
|
if (result) {
|
|
delete result.parent;
|
|
}
|
|
return result;
|
|
}
|
|
/**
|
|
* Finds the node at the given path in a JSON DOM.
|
|
*/
|
|
function findNodeAtLocation(root, path) {
|
|
if (!root) {
|
|
return void 0;
|
|
}
|
|
var node = root;
|
|
for (var _i = 0, path_1 = path; _i < path_1.length; _i++) {
|
|
var segment = path_1[_i];
|
|
if (typeof segment === 'string') {
|
|
if (node.type !== 'object' || !Array.isArray(node.children)) {
|
|
return void 0;
|
|
}
|
|
var found = false;
|
|
for (var _a = 0, _b = node.children; _a < _b.length; _a++) {
|
|
var propertyNode = _b[_a];
|
|
if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment) {
|
|
node = propertyNode.children[1];
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
return void 0;
|
|
}
|
|
}
|
|
else {
|
|
var index = segment;
|
|
if (node.type !== 'array' || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {
|
|
return void 0;
|
|
}
|
|
node = node.children[index];
|
|
}
|
|
}
|
|
return node;
|
|
}
|
|
/**
|
|
* Gets the JSON path of the given JSON DOM node
|
|
*/
|
|
function getNodePath(node) {
|
|
if (!node.parent || !node.parent.children) {
|
|
return [];
|
|
}
|
|
var path = getNodePath(node.parent);
|
|
if (node.parent.type === 'property') {
|
|
var key = node.parent.children[0].value;
|
|
path.push(key);
|
|
}
|
|
else if (node.parent.type === 'array') {
|
|
var index = node.parent.children.indexOf(node);
|
|
if (index !== -1) {
|
|
path.push(index);
|
|
}
|
|
}
|
|
return path;
|
|
}
|
|
/**
|
|
* Evaluates the JavaScript object of the given JSON DOM node
|
|
*/
|
|
function getNodeValue(node) {
|
|
switch (node.type) {
|
|
case 'array':
|
|
return node.children.map(getNodeValue);
|
|
case 'object':
|
|
var obj = Object.create(null);
|
|
for (var _i = 0, _a = node.children; _i < _a.length; _i++) {
|
|
var prop = _a[_i];
|
|
var valueNode = prop.children[1];
|
|
if (valueNode) {
|
|
obj[prop.children[0].value] = getNodeValue(valueNode);
|
|
}
|
|
}
|
|
return obj;
|
|
case 'null':
|
|
case 'string':
|
|
case 'number':
|
|
case 'boolean':
|
|
return node.value;
|
|
default:
|
|
return void 0;
|
|
}
|
|
}
|
|
function contains(node, offset, includeRightBound) {
|
|
if (includeRightBound === void 0) { includeRightBound = false; }
|
|
return (offset >= node.offset && offset < (node.offset + node.length)) || includeRightBound && (offset === (node.offset + node.length));
|
|
}
|
|
/**
|
|
* Finds the most inner node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.
|
|
*/
|
|
function findNodeAtOffset(node, offset, includeRightBound) {
|
|
if (includeRightBound === void 0) { includeRightBound = false; }
|
|
if (contains(node, offset, includeRightBound)) {
|
|
var children = node.children;
|
|
if (Array.isArray(children)) {
|
|
for (var i = 0; i < children.length && children[i].offset <= offset; i++) {
|
|
var item = findNodeAtOffset(children[i], offset, includeRightBound);
|
|
if (item) {
|
|
return item;
|
|
}
|
|
}
|
|
}
|
|
return node;
|
|
}
|
|
return void 0;
|
|
}
|
|
/**
|
|
* Parses the given text and invokes the visitor functions for each object, array and literal reached.
|
|
*/
|
|
function visit(text, visitor, options) {
|
|
if (options === void 0) { options = ParseOptions.DEFAULT; }
|
|
var _scanner = Object(_scanner__WEBPACK_IMPORTED_MODULE_0__["createScanner"])(text, false);
|
|
function toNoArgVisit(visitFunction) {
|
|
return visitFunction ? function () { return visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()); } : function () { return true; };
|
|
}
|
|
function toOneArgVisit(visitFunction) {
|
|
return visitFunction ? function (arg) { return visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()); } : function () { return true; };
|
|
}
|
|
var onObjectBegin = toNoArgVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisit(visitor.onObjectProperty), onObjectEnd = toNoArgVisit(visitor.onObjectEnd), onArrayBegin = toNoArgVisit(visitor.onArrayBegin), onArrayEnd = toNoArgVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisit(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);
|
|
var disallowComments = options && options.disallowComments;
|
|
var allowTrailingComma = options && options.allowTrailingComma;
|
|
function scanNext() {
|
|
while (true) {
|
|
var token = _scanner.scan();
|
|
switch (_scanner.getTokenError()) {
|
|
case 4 /* InvalidUnicode */:
|
|
handleError(14 /* InvalidUnicode */);
|
|
break;
|
|
case 5 /* InvalidEscapeCharacter */:
|
|
handleError(15 /* InvalidEscapeCharacter */);
|
|
break;
|
|
case 3 /* UnexpectedEndOfNumber */:
|
|
handleError(13 /* UnexpectedEndOfNumber */);
|
|
break;
|
|
case 1 /* UnexpectedEndOfComment */:
|
|
if (!disallowComments) {
|
|
handleError(11 /* UnexpectedEndOfComment */);
|
|
}
|
|
break;
|
|
case 2 /* UnexpectedEndOfString */:
|
|
handleError(12 /* UnexpectedEndOfString */);
|
|
break;
|
|
case 6 /* InvalidCharacter */:
|
|
handleError(16 /* InvalidCharacter */);
|
|
break;
|
|
}
|
|
switch (token) {
|
|
case 12 /* LineCommentTrivia */:
|
|
case 13 /* BlockCommentTrivia */:
|
|
if (disallowComments) {
|
|
handleError(10 /* InvalidCommentToken */);
|
|
}
|
|
else {
|
|
onComment();
|
|
}
|
|
break;
|
|
case 16 /* Unknown */:
|
|
handleError(1 /* InvalidSymbol */);
|
|
break;
|
|
case 15 /* Trivia */:
|
|
case 14 /* LineBreakTrivia */:
|
|
break;
|
|
default:
|
|
return token;
|
|
}
|
|
}
|
|
}
|
|
function handleError(error, skipUntilAfter, skipUntil) {
|
|
if (skipUntilAfter === void 0) { skipUntilAfter = []; }
|
|
if (skipUntil === void 0) { skipUntil = []; }
|
|
onError(error);
|
|
if (skipUntilAfter.length + skipUntil.length > 0) {
|
|
var token = _scanner.getToken();
|
|
while (token !== 17 /* EOF */) {
|
|
if (skipUntilAfter.indexOf(token) !== -1) {
|
|
scanNext();
|
|
break;
|
|
}
|
|
else if (skipUntil.indexOf(token) !== -1) {
|
|
break;
|
|
}
|
|
token = scanNext();
|
|
}
|
|
}
|
|
}
|
|
function parseString(isValue) {
|
|
var value = _scanner.getTokenValue();
|
|
if (isValue) {
|
|
onLiteralValue(value);
|
|
}
|
|
else {
|
|
onObjectProperty(value);
|
|
}
|
|
scanNext();
|
|
return true;
|
|
}
|
|
function parseLiteral() {
|
|
switch (_scanner.getToken()) {
|
|
case 11 /* NumericLiteral */:
|
|
var value = 0;
|
|
try {
|
|
value = JSON.parse(_scanner.getTokenValue());
|
|
if (typeof value !== 'number') {
|
|
handleError(2 /* InvalidNumberFormat */);
|
|
value = 0;
|
|
}
|
|
}
|
|
catch (e) {
|
|
handleError(2 /* InvalidNumberFormat */);
|
|
}
|
|
onLiteralValue(value);
|
|
break;
|
|
case 7 /* NullKeyword */:
|
|
onLiteralValue(null);
|
|
break;
|
|
case 8 /* TrueKeyword */:
|
|
onLiteralValue(true);
|
|
break;
|
|
case 9 /* FalseKeyword */:
|
|
onLiteralValue(false);
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
scanNext();
|
|
return true;
|
|
}
|
|
function parseProperty() {
|
|
if (_scanner.getToken() !== 10 /* StringLiteral */) {
|
|
handleError(3 /* PropertyNameExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);
|
|
return false;
|
|
}
|
|
parseString(false);
|
|
if (_scanner.getToken() === 6 /* ColonToken */) {
|
|
onSeparator(':');
|
|
scanNext(); // consume colon
|
|
if (!parseValue()) {
|
|
handleError(4 /* ValueExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);
|
|
}
|
|
}
|
|
else {
|
|
handleError(5 /* ColonExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);
|
|
}
|
|
return true;
|
|
}
|
|
function parseObject() {
|
|
onObjectBegin();
|
|
scanNext(); // consume open brace
|
|
var needsComma = false;
|
|
while (_scanner.getToken() !== 2 /* CloseBraceToken */ && _scanner.getToken() !== 17 /* EOF */) {
|
|
if (_scanner.getToken() === 5 /* CommaToken */) {
|
|
if (!needsComma) {
|
|
handleError(4 /* ValueExpected */, [], []);
|
|
}
|
|
onSeparator(',');
|
|
scanNext(); // consume comma
|
|
if (_scanner.getToken() === 2 /* CloseBraceToken */ && allowTrailingComma) {
|
|
break;
|
|
}
|
|
}
|
|
else if (needsComma) {
|
|
handleError(6 /* CommaExpected */, [], []);
|
|
}
|
|
if (!parseProperty()) {
|
|
handleError(4 /* ValueExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);
|
|
}
|
|
needsComma = true;
|
|
}
|
|
onObjectEnd();
|
|
if (_scanner.getToken() !== 2 /* CloseBraceToken */) {
|
|
handleError(7 /* CloseBraceExpected */, [2 /* CloseBraceToken */], []);
|
|
}
|
|
else {
|
|
scanNext(); // consume close brace
|
|
}
|
|
return true;
|
|
}
|
|
function parseArray() {
|
|
onArrayBegin();
|
|
scanNext(); // consume open bracket
|
|
var needsComma = false;
|
|
while (_scanner.getToken() !== 4 /* CloseBracketToken */ && _scanner.getToken() !== 17 /* EOF */) {
|
|
if (_scanner.getToken() === 5 /* CommaToken */) {
|
|
if (!needsComma) {
|
|
handleError(4 /* ValueExpected */, [], []);
|
|
}
|
|
onSeparator(',');
|
|
scanNext(); // consume comma
|
|
if (_scanner.getToken() === 4 /* CloseBracketToken */ && allowTrailingComma) {
|
|
break;
|
|
}
|
|
}
|
|
else if (needsComma) {
|
|
handleError(6 /* CommaExpected */, [], []);
|
|
}
|
|
if (!parseValue()) {
|
|
handleError(4 /* ValueExpected */, [], [4 /* CloseBracketToken */, 5 /* CommaToken */]);
|
|
}
|
|
needsComma = true;
|
|
}
|
|
onArrayEnd();
|
|
if (_scanner.getToken() !== 4 /* CloseBracketToken */) {
|
|
handleError(8 /* CloseBracketExpected */, [4 /* CloseBracketToken */], []);
|
|
}
|
|
else {
|
|
scanNext(); // consume close bracket
|
|
}
|
|
return true;
|
|
}
|
|
function parseValue() {
|
|
switch (_scanner.getToken()) {
|
|
case 3 /* OpenBracketToken */:
|
|
return parseArray();
|
|
case 1 /* OpenBraceToken */:
|
|
return parseObject();
|
|
case 10 /* StringLiteral */:
|
|
return parseString(true);
|
|
default:
|
|
return parseLiteral();
|
|
}
|
|
}
|
|
scanNext();
|
|
if (_scanner.getToken() === 17 /* EOF */) {
|
|
return true;
|
|
}
|
|
if (!parseValue()) {
|
|
handleError(4 /* ValueExpected */, [], []);
|
|
return false;
|
|
}
|
|
if (_scanner.getToken() !== 17 /* EOF */) {
|
|
handleError(9 /* EndOfFileExpected */, [], []);
|
|
}
|
|
return true;
|
|
}
|
|
/**
|
|
* Takes JSON with JavaScript-style comments and remove
|
|
* them. Optionally replaces every none-newline character
|
|
* of comments with a replaceCharacter
|
|
*/
|
|
function stripComments(text, replaceCh) {
|
|
var _scanner = Object(_scanner__WEBPACK_IMPORTED_MODULE_0__["createScanner"])(text), parts = [], kind, offset = 0, pos;
|
|
do {
|
|
pos = _scanner.getPosition();
|
|
kind = _scanner.scan();
|
|
switch (kind) {
|
|
case 12 /* LineCommentTrivia */:
|
|
case 13 /* BlockCommentTrivia */:
|
|
case 17 /* EOF */:
|
|
if (offset !== pos) {
|
|
parts.push(text.substring(offset, pos));
|
|
}
|
|
if (replaceCh !== void 0) {
|
|
parts.push(_scanner.getTokenValue().replace(/[^\r\n]/g, replaceCh));
|
|
}
|
|
offset = _scanner.getPosition();
|
|
break;
|
|
}
|
|
} while (kind !== 17 /* EOF */);
|
|
return parts.join('');
|
|
}
|
|
function getLiteralNodeType(value) {
|
|
switch (typeof value) {
|
|
case 'boolean': return 'boolean';
|
|
case 'number': return 'number';
|
|
case 'string': return 'string';
|
|
default: return 'null';
|
|
}
|
|
}
|
|
//# sourceMappingURL=parser.js.map
|
|
|
|
/***/ }),
|
|
/* 200 */
|
|
/***/ (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__(175);
|
|
const fs_1 = tslib_1.__importDefault(__webpack_require__(55));
|
|
const net_1 = tslib_1.__importDefault(__webpack_require__(6));
|
|
const os_1 = tslib_1.__importDefault(__webpack_require__(56));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const readline_1 = tslib_1.__importDefault(__webpack_require__(60));
|
|
const util_1 = tslib_1.__importDefault(__webpack_require__(40));
|
|
const minimatch_1 = tslib_1.__importDefault(__webpack_require__(201));
|
|
const logger = __webpack_require__(186)('util-fs');
|
|
async function statAsync(filepath) {
|
|
let stat = null;
|
|
try {
|
|
stat = await util_1.default.promisify(fs_1.default.stat)(filepath);
|
|
}
|
|
catch (e) { } // tslint:disable-line
|
|
return stat;
|
|
}
|
|
exports.statAsync = statAsync;
|
|
async function isDirectory(filepath) {
|
|
let stat = await statAsync(filepath);
|
|
return stat && stat.isDirectory();
|
|
}
|
|
exports.isDirectory = isDirectory;
|
|
async function unlinkAsync(filepath) {
|
|
try {
|
|
await util_1.default.promisify(fs_1.default.unlink)(filepath);
|
|
}
|
|
catch (e) { } // tslint:disable-line
|
|
}
|
|
exports.unlinkAsync = unlinkAsync;
|
|
function renameAsync(oldPath, newPath) {
|
|
return new Promise((resolve, reject) => {
|
|
fs_1.default.rename(oldPath, newPath, err => {
|
|
if (err)
|
|
return reject(err);
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
exports.renameAsync = renameAsync;
|
|
async function isGitIgnored(fullpath) {
|
|
if (!fullpath)
|
|
return false;
|
|
let stat = await statAsync(fullpath);
|
|
if (!stat || !stat.isFile())
|
|
return false;
|
|
let root = null;
|
|
try {
|
|
let { stdout } = await util_1.default.promisify(child_process_1.exec)('git rev-parse --show-toplevel', { cwd: path_1.default.dirname(fullpath) });
|
|
root = stdout.trim();
|
|
}
|
|
catch (e) { } // tslint:disable-line
|
|
if (!root)
|
|
return false;
|
|
let file = path_1.default.relative(root, fullpath);
|
|
try {
|
|
let { stdout } = await util_1.default.promisify(child_process_1.exec)(`git check-ignore ${file}`, { cwd: root });
|
|
return stdout.trim() == file;
|
|
}
|
|
catch (e) { } // tslint:disable-line
|
|
return false;
|
|
}
|
|
exports.isGitIgnored = isGitIgnored;
|
|
function resolveRoot(dir, subs, cwd) {
|
|
let home = os_1.default.homedir();
|
|
if (isParentFolder(dir, home, true))
|
|
return null;
|
|
if (cwd && isParentFolder(cwd, dir, true) && inDirectory(cwd, subs))
|
|
return cwd;
|
|
let parts = dir.split(path_1.default.sep);
|
|
let curr = [parts.shift()];
|
|
for (let part of parts) {
|
|
curr.push(part);
|
|
let dir = curr.join(path_1.default.sep);
|
|
if (dir != home && inDirectory(dir, subs)) {
|
|
return dir;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
exports.resolveRoot = resolveRoot;
|
|
function inDirectory(dir, subs) {
|
|
try {
|
|
let files = fs_1.default.readdirSync(dir);
|
|
for (let pattern of subs) {
|
|
// note, only '*' expanded
|
|
let is_wildcard = (pattern.indexOf('*') !== -1);
|
|
let res = is_wildcard ?
|
|
(minimatch_1.default.match(files, pattern, { nobrace: true, noext: true, nocomment: true, nonegate: true, dot: true }).length !== 0) :
|
|
(files.indexOf(pattern) !== -1);
|
|
if (res)
|
|
return true;
|
|
}
|
|
}
|
|
catch (e) {
|
|
// could be failed without permission
|
|
}
|
|
return false;
|
|
}
|
|
exports.inDirectory = inDirectory;
|
|
function findUp(name, cwd) {
|
|
let root = path_1.default.parse(cwd).root;
|
|
let subs = Array.isArray(name) ? name : [name];
|
|
while (cwd && cwd !== root) {
|
|
let find = inDirectory(cwd, subs);
|
|
if (find) {
|
|
for (let sub of subs) {
|
|
let filepath = path_1.default.join(cwd, sub);
|
|
if (fs_1.default.existsSync(filepath)) {
|
|
return filepath;
|
|
}
|
|
}
|
|
}
|
|
cwd = path_1.default.dirname(cwd);
|
|
}
|
|
return null;
|
|
}
|
|
exports.findUp = findUp;
|
|
function readFile(fullpath, encoding) {
|
|
return new Promise((resolve, reject) => {
|
|
fs_1.default.readFile(fullpath, encoding, (err, content) => {
|
|
if (err)
|
|
reject(err);
|
|
resolve(content);
|
|
});
|
|
});
|
|
}
|
|
exports.readFile = readFile;
|
|
function getFileLineCount(filepath) {
|
|
let i;
|
|
let count = 0;
|
|
return new Promise((resolve, reject) => {
|
|
fs_1.default.createReadStream(filepath)
|
|
.on('error', e => reject(e))
|
|
.on('data', chunk => {
|
|
for (i = 0; i < chunk.length; ++i)
|
|
if (chunk[i] == 10)
|
|
count++;
|
|
})
|
|
.on('end', () => resolve(count));
|
|
});
|
|
}
|
|
exports.getFileLineCount = getFileLineCount;
|
|
function readFileLines(fullpath, start, end) {
|
|
let res = [];
|
|
const rl = readline_1.default.createInterface({
|
|
input: fs_1.default.createReadStream(fullpath, { encoding: 'utf8' }),
|
|
crlfDelay: Infinity,
|
|
terminal: false
|
|
});
|
|
let n = 0;
|
|
return new Promise((resolve, reject) => {
|
|
rl.on('line', line => {
|
|
if (n == 0 && line.startsWith('\uFEFF')) {
|
|
// handle BOM
|
|
line = line.slice(1);
|
|
}
|
|
if (n >= start && n <= end) {
|
|
res.push(line);
|
|
}
|
|
if (n == end) {
|
|
rl.close();
|
|
}
|
|
n = n + 1;
|
|
});
|
|
rl.on('close', () => {
|
|
resolve(res);
|
|
});
|
|
rl.on('error', reject);
|
|
});
|
|
}
|
|
exports.readFileLines = readFileLines;
|
|
function readFileLine(fullpath, count) {
|
|
const rl = readline_1.default.createInterface({
|
|
input: fs_1.default.createReadStream(fullpath, { encoding: 'utf8' }),
|
|
crlfDelay: Infinity,
|
|
terminal: false
|
|
});
|
|
let n = 0;
|
|
return new Promise((resolve, reject) => {
|
|
rl.on('line', line => {
|
|
if (n == count) {
|
|
if (n == 0 && line.startsWith('\uFEFF')) {
|
|
// handle BOM
|
|
line = line.slice(1);
|
|
}
|
|
rl.close();
|
|
resolve(line);
|
|
return;
|
|
}
|
|
n = n + 1;
|
|
});
|
|
rl.on('error', reject);
|
|
});
|
|
}
|
|
exports.readFileLine = readFileLine;
|
|
async function writeFile(fullpath, content) {
|
|
await util_1.default.promisify(fs_1.default.writeFile)(fullpath, content, 'utf8');
|
|
}
|
|
exports.writeFile = writeFile;
|
|
function validSocket(path) {
|
|
let clientSocket = new net_1.default.Socket();
|
|
return new Promise(resolve => {
|
|
clientSocket.on('error', () => {
|
|
resolve(false);
|
|
});
|
|
clientSocket.connect({ path }, () => {
|
|
clientSocket.unref();
|
|
resolve(true);
|
|
});
|
|
});
|
|
}
|
|
exports.validSocket = validSocket;
|
|
function isFile(uri) {
|
|
return uri.startsWith('file:');
|
|
}
|
|
exports.isFile = isFile;
|
|
exports.readdirAsync = util_1.default.promisify(fs_1.default.readdir);
|
|
exports.realpathAsync = util_1.default.promisify(fs_1.default.realpath);
|
|
function parentDirs(pth) {
|
|
let { root, dir } = path_1.default.parse(pth);
|
|
if (dir === root)
|
|
return [root];
|
|
const dirs = [root];
|
|
const parts = dir.slice(root.length).split(path_1.default.sep);
|
|
for (let i = 1; i <= parts.length; i++) {
|
|
dirs.push(path_1.default.join(root, parts.slice(0, i).join(path_1.default.sep)));
|
|
}
|
|
return dirs;
|
|
}
|
|
exports.parentDirs = parentDirs;
|
|
function isParentFolder(folder, filepath, checkEqual = false) {
|
|
let pdir = fixDriver(path_1.default.resolve(path_1.default.normalize(folder)));
|
|
let dir = fixDriver(path_1.default.resolve(path_1.default.normalize(filepath)));
|
|
if (pdir == '//')
|
|
pdir = '/';
|
|
if (pdir == dir)
|
|
return checkEqual ? true : false;
|
|
if (pdir.endsWith(path_1.default.sep))
|
|
return dir.startsWith(pdir);
|
|
return dir.startsWith(pdir) && dir[pdir.length] == path_1.default.sep;
|
|
}
|
|
exports.isParentFolder = isParentFolder;
|
|
// use uppercase for windows driver
|
|
function fixDriver(filepath) {
|
|
if (os_1.default.platform() != 'win32' || filepath[1] != ':')
|
|
return filepath;
|
|
return filepath[0].toUpperCase() + filepath.slice(1);
|
|
}
|
|
exports.fixDriver = fixDriver;
|
|
//# sourceMappingURL=fs.js.map
|
|
|
|
/***/ }),
|
|
/* 201 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
module.exports = minimatch
|
|
minimatch.Minimatch = Minimatch
|
|
|
|
var path = { sep: '/' }
|
|
try {
|
|
path = __webpack_require__(57)
|
|
} catch (er) {}
|
|
|
|
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
|
|
var expand = __webpack_require__(202)
|
|
|
|
var plTypes = {
|
|
'!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
|
|
'?': { open: '(?:', close: ')?' },
|
|
'+': { open: '(?:', close: ')+' },
|
|
'*': { open: '(?:', close: ')*' },
|
|
'@': { open: '(?:', close: ')' }
|
|
}
|
|
|
|
// any single thing other than /
|
|
// don't need to escape / when using new RegExp()
|
|
var qmark = '[^/]'
|
|
|
|
// * => any number of characters
|
|
var star = qmark + '*?'
|
|
|
|
// ** when dots are allowed. Anything goes, except .. and .
|
|
// not (^ or / followed by one or two dots followed by $ or /),
|
|
// followed by anything, any number of times.
|
|
var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
|
|
|
|
// not a ^ or / followed by a dot,
|
|
// followed by anything, any number of times.
|
|
var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
|
|
|
|
// characters that need to be escaped in RegExp.
|
|
var reSpecials = charSet('().*{}+?[]^$\\!')
|
|
|
|
// "abc" -> { a:true, b:true, c:true }
|
|
function charSet (s) {
|
|
return s.split('').reduce(function (set, c) {
|
|
set[c] = true
|
|
return set
|
|
}, {})
|
|
}
|
|
|
|
// normalizes slashes.
|
|
var slashSplit = /\/+/
|
|
|
|
minimatch.filter = filter
|
|
function filter (pattern, options) {
|
|
options = options || {}
|
|
return function (p, i, list) {
|
|
return minimatch(p, pattern, options)
|
|
}
|
|
}
|
|
|
|
function ext (a, b) {
|
|
a = a || {}
|
|
b = b || {}
|
|
var t = {}
|
|
Object.keys(b).forEach(function (k) {
|
|
t[k] = b[k]
|
|
})
|
|
Object.keys(a).forEach(function (k) {
|
|
t[k] = a[k]
|
|
})
|
|
return t
|
|
}
|
|
|
|
minimatch.defaults = function (def) {
|
|
if (!def || !Object.keys(def).length) return minimatch
|
|
|
|
var orig = minimatch
|
|
|
|
var m = function minimatch (p, pattern, options) {
|
|
return orig.minimatch(p, pattern, ext(def, options))
|
|
}
|
|
|
|
m.Minimatch = function Minimatch (pattern, options) {
|
|
return new orig.Minimatch(pattern, ext(def, options))
|
|
}
|
|
|
|
return m
|
|
}
|
|
|
|
Minimatch.defaults = function (def) {
|
|
if (!def || !Object.keys(def).length) return Minimatch
|
|
return minimatch.defaults(def).Minimatch
|
|
}
|
|
|
|
function minimatch (p, pattern, options) {
|
|
if (typeof pattern !== 'string') {
|
|
throw new TypeError('glob pattern string required')
|
|
}
|
|
|
|
if (!options) options = {}
|
|
|
|
// shortcut: comments match nothing.
|
|
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|
return false
|
|
}
|
|
|
|
// "" only matches ""
|
|
if (pattern.trim() === '') return p === ''
|
|
|
|
return new Minimatch(pattern, options).match(p)
|
|
}
|
|
|
|
function Minimatch (pattern, options) {
|
|
if (!(this instanceof Minimatch)) {
|
|
return new Minimatch(pattern, options)
|
|
}
|
|
|
|
if (typeof pattern !== 'string') {
|
|
throw new TypeError('glob pattern string required')
|
|
}
|
|
|
|
if (!options) options = {}
|
|
pattern = pattern.trim()
|
|
|
|
// windows support: need to use /, not \
|
|
if (path.sep !== '/') {
|
|
pattern = pattern.split(path.sep).join('/')
|
|
}
|
|
|
|
this.options = options
|
|
this.set = []
|
|
this.pattern = pattern
|
|
this.regexp = null
|
|
this.negate = false
|
|
this.comment = false
|
|
this.empty = false
|
|
|
|
// make the set of regexps etc.
|
|
this.make()
|
|
}
|
|
|
|
Minimatch.prototype.debug = function () {}
|
|
|
|
Minimatch.prototype.make = make
|
|
function make () {
|
|
// don't do it more than once.
|
|
if (this._made) return
|
|
|
|
var pattern = this.pattern
|
|
var options = this.options
|
|
|
|
// empty patterns and comments match nothing.
|
|
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|
this.comment = true
|
|
return
|
|
}
|
|
if (!pattern) {
|
|
this.empty = true
|
|
return
|
|
}
|
|
|
|
// step 1: figure out negation, etc.
|
|
this.parseNegate()
|
|
|
|
// step 2: expand braces
|
|
var set = this.globSet = this.braceExpand()
|
|
|
|
if (options.debug) this.debug = console.error
|
|
|
|
this.debug(this.pattern, set)
|
|
|
|
// step 3: now we have a set, so turn each one into a series of path-portion
|
|
// matching patterns.
|
|
// These will be regexps, except in the case of "**", which is
|
|
// set to the GLOBSTAR object for globstar behavior,
|
|
// and will not contain any / characters
|
|
set = this.globParts = set.map(function (s) {
|
|
return s.split(slashSplit)
|
|
})
|
|
|
|
this.debug(this.pattern, set)
|
|
|
|
// glob --> regexps
|
|
set = set.map(function (s, si, set) {
|
|
return s.map(this.parse, this)
|
|
}, this)
|
|
|
|
this.debug(this.pattern, set)
|
|
|
|
// filter out everything that didn't compile properly.
|
|
set = set.filter(function (s) {
|
|
return s.indexOf(false) === -1
|
|
})
|
|
|
|
this.debug(this.pattern, set)
|
|
|
|
this.set = set
|
|
}
|
|
|
|
Minimatch.prototype.parseNegate = parseNegate
|
|
function parseNegate () {
|
|
var pattern = this.pattern
|
|
var negate = false
|
|
var options = this.options
|
|
var negateOffset = 0
|
|
|
|
if (options.nonegate) return
|
|
|
|
for (var i = 0, l = pattern.length
|
|
; i < l && pattern.charAt(i) === '!'
|
|
; i++) {
|
|
negate = !negate
|
|
negateOffset++
|
|
}
|
|
|
|
if (negateOffset) this.pattern = pattern.substr(negateOffset)
|
|
this.negate = negate
|
|
}
|
|
|
|
// Brace expansion:
|
|
// a{b,c}d -> abd acd
|
|
// a{b,}c -> abc ac
|
|
// a{0..3}d -> a0d a1d a2d a3d
|
|
// a{b,c{d,e}f}g -> abg acdfg acefg
|
|
// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
|
|
//
|
|
// Invalid sets are not expanded.
|
|
// a{2..}b -> a{2..}b
|
|
// a{b}c -> a{b}c
|
|
minimatch.braceExpand = function (pattern, options) {
|
|
return braceExpand(pattern, options)
|
|
}
|
|
|
|
Minimatch.prototype.braceExpand = braceExpand
|
|
|
|
function braceExpand (pattern, options) {
|
|
if (!options) {
|
|
if (this instanceof Minimatch) {
|
|
options = this.options
|
|
} else {
|
|
options = {}
|
|
}
|
|
}
|
|
|
|
pattern = typeof pattern === 'undefined'
|
|
? this.pattern : pattern
|
|
|
|
if (typeof pattern === 'undefined') {
|
|
throw new TypeError('undefined pattern')
|
|
}
|
|
|
|
if (options.nobrace ||
|
|
!pattern.match(/\{.*\}/)) {
|
|
// shortcut. no need to expand.
|
|
return [pattern]
|
|
}
|
|
|
|
return expand(pattern)
|
|
}
|
|
|
|
// parse a component of the expanded set.
|
|
// At this point, no pattern may contain "/" in it
|
|
// so we're going to return a 2d array, where each entry is the full
|
|
// pattern, split on '/', and then turned into a regular expression.
|
|
// A regexp is made at the end which joins each array with an
|
|
// escaped /, and another full one which joins each regexp with |.
|
|
//
|
|
// Following the lead of Bash 4.1, note that "**" only has special meaning
|
|
// when it is the *only* thing in a path portion. Otherwise, any series
|
|
// of * is equivalent to a single *. Globstar behavior is enabled by
|
|
// default, and can be disabled by setting options.noglobstar.
|
|
Minimatch.prototype.parse = parse
|
|
var SUBPARSE = {}
|
|
function parse (pattern, isSub) {
|
|
if (pattern.length > 1024 * 64) {
|
|
throw new TypeError('pattern is too long')
|
|
}
|
|
|
|
var options = this.options
|
|
|
|
// shortcuts
|
|
if (!options.noglobstar && pattern === '**') return GLOBSTAR
|
|
if (pattern === '') return ''
|
|
|
|
var re = ''
|
|
var hasMagic = !!options.nocase
|
|
var escaping = false
|
|
// ? => one single character
|
|
var patternListStack = []
|
|
var negativeLists = []
|
|
var stateChar
|
|
var inClass = false
|
|
var reClassStart = -1
|
|
var classStart = -1
|
|
// . and .. never match anything that doesn't start with .,
|
|
// even when options.dot is set.
|
|
var patternStart = pattern.charAt(0) === '.' ? '' // anything
|
|
// not (start or / followed by . or .. followed by / or end)
|
|
: options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
|
|
: '(?!\\.)'
|
|
var self = this
|
|
|
|
function clearStateChar () {
|
|
if (stateChar) {
|
|
// we had some state-tracking character
|
|
// that wasn't consumed by this pass.
|
|
switch (stateChar) {
|
|
case '*':
|
|
re += star
|
|
hasMagic = true
|
|
break
|
|
case '?':
|
|
re += qmark
|
|
hasMagic = true
|
|
break
|
|
default:
|
|
re += '\\' + stateChar
|
|
break
|
|
}
|
|
self.debug('clearStateChar %j %j', stateChar, re)
|
|
stateChar = false
|
|
}
|
|
}
|
|
|
|
for (var i = 0, len = pattern.length, c
|
|
; (i < len) && (c = pattern.charAt(i))
|
|
; i++) {
|
|
this.debug('%s\t%s %s %j', pattern, i, re, c)
|
|
|
|
// skip over any that are escaped.
|
|
if (escaping && reSpecials[c]) {
|
|
re += '\\' + c
|
|
escaping = false
|
|
continue
|
|
}
|
|
|
|
switch (c) {
|
|
case '/':
|
|
// completely not allowed, even escaped.
|
|
// Should already be path-split by now.
|
|
return false
|
|
|
|
case '\\':
|
|
clearStateChar()
|
|
escaping = true
|
|
continue
|
|
|
|
// the various stateChar values
|
|
// for the "extglob" stuff.
|
|
case '?':
|
|
case '*':
|
|
case '+':
|
|
case '@':
|
|
case '!':
|
|
this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
|
|
|
|
// all of those are literals inside a class, except that
|
|
// the glob [!a] means [^a] in regexp
|
|
if (inClass) {
|
|
this.debug(' in class')
|
|
if (c === '!' && i === classStart + 1) c = '^'
|
|
re += c
|
|
continue
|
|
}
|
|
|
|
// if we already have a stateChar, then it means
|
|
// that there was something like ** or +? in there.
|
|
// Handle the stateChar, then proceed with this one.
|
|
self.debug('call clearStateChar %j', stateChar)
|
|
clearStateChar()
|
|
stateChar = c
|
|
// if extglob is disabled, then +(asdf|foo) isn't a thing.
|
|
// just clear the statechar *now*, rather than even diving into
|
|
// the patternList stuff.
|
|
if (options.noext) clearStateChar()
|
|
continue
|
|
|
|
case '(':
|
|
if (inClass) {
|
|
re += '('
|
|
continue
|
|
}
|
|
|
|
if (!stateChar) {
|
|
re += '\\('
|
|
continue
|
|
}
|
|
|
|
patternListStack.push({
|
|
type: stateChar,
|
|
start: i - 1,
|
|
reStart: re.length,
|
|
open: plTypes[stateChar].open,
|
|
close: plTypes[stateChar].close
|
|
})
|
|
// negation is (?:(?!js)[^/]*)
|
|
re += stateChar === '!' ? '(?:(?!(?:' : '(?:'
|
|
this.debug('plType %j %j', stateChar, re)
|
|
stateChar = false
|
|
continue
|
|
|
|
case ')':
|
|
if (inClass || !patternListStack.length) {
|
|
re += '\\)'
|
|
continue
|
|
}
|
|
|
|
clearStateChar()
|
|
hasMagic = true
|
|
var pl = patternListStack.pop()
|
|
// negation is (?:(?!js)[^/]*)
|
|
// The others are (?:<pattern>)<type>
|
|
re += pl.close
|
|
if (pl.type === '!') {
|
|
negativeLists.push(pl)
|
|
}
|
|
pl.reEnd = re.length
|
|
continue
|
|
|
|
case '|':
|
|
if (inClass || !patternListStack.length || escaping) {
|
|
re += '\\|'
|
|
escaping = false
|
|
continue
|
|
}
|
|
|
|
clearStateChar()
|
|
re += '|'
|
|
continue
|
|
|
|
// these are mostly the same in regexp and glob
|
|
case '[':
|
|
// swallow any state-tracking char before the [
|
|
clearStateChar()
|
|
|
|
if (inClass) {
|
|
re += '\\' + c
|
|
continue
|
|
}
|
|
|
|
inClass = true
|
|
classStart = i
|
|
reClassStart = re.length
|
|
re += c
|
|
continue
|
|
|
|
case ']':
|
|
// a right bracket shall lose its special
|
|
// meaning and represent itself in
|
|
// a bracket expression if it occurs
|
|
// first in the list. -- POSIX.2 2.8.3.2
|
|
if (i === classStart + 1 || !inClass) {
|
|
re += '\\' + c
|
|
escaping = false
|
|
continue
|
|
}
|
|
|
|
// handle the case where we left a class open.
|
|
// "[z-a]" is valid, equivalent to "\[z-a\]"
|
|
if (inClass) {
|
|
// split where the last [ was, make sure we don't have
|
|
// an invalid re. if so, re-walk the contents of the
|
|
// would-be class to re-translate any characters that
|
|
// were passed through as-is
|
|
// TODO: It would probably be faster to determine this
|
|
// without a try/catch and a new RegExp, but it's tricky
|
|
// to do safely. For now, this is safe and works.
|
|
var cs = pattern.substring(classStart + 1, i)
|
|
try {
|
|
RegExp('[' + cs + ']')
|
|
} catch (er) {
|
|
// not a valid class!
|
|
var sp = this.parse(cs, SUBPARSE)
|
|
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
|
|
hasMagic = hasMagic || sp[1]
|
|
inClass = false
|
|
continue
|
|
}
|
|
}
|
|
|
|
// finish up the class.
|
|
hasMagic = true
|
|
inClass = false
|
|
re += c
|
|
continue
|
|
|
|
default:
|
|
// swallow any state char that wasn't consumed
|
|
clearStateChar()
|
|
|
|
if (escaping) {
|
|
// no need
|
|
escaping = false
|
|
} else if (reSpecials[c]
|
|
&& !(c === '^' && inClass)) {
|
|
re += '\\'
|
|
}
|
|
|
|
re += c
|
|
|
|
} // switch
|
|
} // for
|
|
|
|
// handle the case where we left a class open.
|
|
// "[abc" is valid, equivalent to "\[abc"
|
|
if (inClass) {
|
|
// split where the last [ was, and escape it
|
|
// this is a huge pita. We now have to re-walk
|
|
// the contents of the would-be class to re-translate
|
|
// any characters that were passed through as-is
|
|
cs = pattern.substr(classStart + 1)
|
|
sp = this.parse(cs, SUBPARSE)
|
|
re = re.substr(0, reClassStart) + '\\[' + sp[0]
|
|
hasMagic = hasMagic || sp[1]
|
|
}
|
|
|
|
// handle the case where we had a +( thing at the *end*
|
|
// of the pattern.
|
|
// each pattern list stack adds 3 chars, and we need to go through
|
|
// and escape any | chars that were passed through as-is for the regexp.
|
|
// Go through and escape them, taking care not to double-escape any
|
|
// | chars that were already escaped.
|
|
for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
|
|
var tail = re.slice(pl.reStart + pl.open.length)
|
|
this.debug('setting tail', re, pl)
|
|
// maybe some even number of \, then maybe 1 \, followed by a |
|
|
tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) {
|
|
if (!$2) {
|
|
// the | isn't already escaped, so escape it.
|
|
$2 = '\\'
|
|
}
|
|
|
|
// need to escape all those slashes *again*, without escaping the
|
|
// one that we need for escaping the | character. As it works out,
|
|
// escaping an even number of slashes can be done by simply repeating
|
|
// it exactly after itself. That's why this trick works.
|
|
//
|
|
// I am sorry that you have to see this.
|
|
return $1 + $1 + $2 + '|'
|
|
})
|
|
|
|
this.debug('tail=%j\n %s', tail, tail, pl, re)
|
|
var t = pl.type === '*' ? star
|
|
: pl.type === '?' ? qmark
|
|
: '\\' + pl.type
|
|
|
|
hasMagic = true
|
|
re = re.slice(0, pl.reStart) + t + '\\(' + tail
|
|
}
|
|
|
|
// handle trailing things that only matter at the very end.
|
|
clearStateChar()
|
|
if (escaping) {
|
|
// trailing \\
|
|
re += '\\\\'
|
|
}
|
|
|
|
// only need to apply the nodot start if the re starts with
|
|
// something that could conceivably capture a dot
|
|
var addPatternStart = false
|
|
switch (re.charAt(0)) {
|
|
case '.':
|
|
case '[':
|
|
case '(': addPatternStart = true
|
|
}
|
|
|
|
// Hack to work around lack of negative lookbehind in JS
|
|
// A pattern like: *.!(x).!(y|z) needs to ensure that a name
|
|
// like 'a.xyz.yz' doesn't match. So, the first negative
|
|
// lookahead, has to look ALL the way ahead, to the end of
|
|
// the pattern.
|
|
for (var n = negativeLists.length - 1; n > -1; n--) {
|
|
var nl = negativeLists[n]
|
|
|
|
var nlBefore = re.slice(0, nl.reStart)
|
|
var nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
|
|
var nlLast = re.slice(nl.reEnd - 8, nl.reEnd)
|
|
var nlAfter = re.slice(nl.reEnd)
|
|
|
|
nlLast += nlAfter
|
|
|
|
// Handle nested stuff like *(*.js|!(*.json)), where open parens
|
|
// mean that we should *not* include the ) in the bit that is considered
|
|
// "after" the negated section.
|
|
var openParensBefore = nlBefore.split('(').length - 1
|
|
var cleanAfter = nlAfter
|
|
for (i = 0; i < openParensBefore; i++) {
|
|
cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
|
|
}
|
|
nlAfter = cleanAfter
|
|
|
|
var dollar = ''
|
|
if (nlAfter === '' && isSub !== SUBPARSE) {
|
|
dollar = '$'
|
|
}
|
|
var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast
|
|
re = newRe
|
|
}
|
|
|
|
// if the re is not "" at this point, then we need to make sure
|
|
// it doesn't match against an empty path part.
|
|
// Otherwise a/* will match a/, which it should not.
|
|
if (re !== '' && hasMagic) {
|
|
re = '(?=.)' + re
|
|
}
|
|
|
|
if (addPatternStart) {
|
|
re = patternStart + re
|
|
}
|
|
|
|
// parsing just a piece of a larger pattern.
|
|
if (isSub === SUBPARSE) {
|
|
return [re, hasMagic]
|
|
}
|
|
|
|
// skip the regexp for non-magical patterns
|
|
// unescape anything in it, though, so that it'll be
|
|
// an exact match against a file etc.
|
|
if (!hasMagic) {
|
|
return globUnescape(pattern)
|
|
}
|
|
|
|
var flags = options.nocase ? 'i' : ''
|
|
try {
|
|
var regExp = new RegExp('^' + re + '$', flags)
|
|
} catch (er) {
|
|
// If it was an invalid regular expression, then it can't match
|
|
// anything. This trick looks for a character after the end of
|
|
// the string, which is of course impossible, except in multi-line
|
|
// mode, but it's not a /m regex.
|
|
return new RegExp('$.')
|
|
}
|
|
|
|
regExp._glob = pattern
|
|
regExp._src = re
|
|
|
|
return regExp
|
|
}
|
|
|
|
minimatch.makeRe = function (pattern, options) {
|
|
return new Minimatch(pattern, options || {}).makeRe()
|
|
}
|
|
|
|
Minimatch.prototype.makeRe = makeRe
|
|
function makeRe () {
|
|
if (this.regexp || this.regexp === false) return this.regexp
|
|
|
|
// at this point, this.set is a 2d array of partial
|
|
// pattern strings, or "**".
|
|
//
|
|
// It's better to use .match(). This function shouldn't
|
|
// be used, really, but it's pretty convenient sometimes,
|
|
// when you just want to work with a regex.
|
|
var set = this.set
|
|
|
|
if (!set.length) {
|
|
this.regexp = false
|
|
return this.regexp
|
|
}
|
|
var options = this.options
|
|
|
|
var twoStar = options.noglobstar ? star
|
|
: options.dot ? twoStarDot
|
|
: twoStarNoDot
|
|
var flags = options.nocase ? 'i' : ''
|
|
|
|
var re = set.map(function (pattern) {
|
|
return pattern.map(function (p) {
|
|
return (p === GLOBSTAR) ? twoStar
|
|
: (typeof p === 'string') ? regExpEscape(p)
|
|
: p._src
|
|
}).join('\\\/')
|
|
}).join('|')
|
|
|
|
// must match entire pattern
|
|
// ending in a * or ** will make it less strict.
|
|
re = '^(?:' + re + ')$'
|
|
|
|
// can match anything, as long as it's not this.
|
|
if (this.negate) re = '^(?!' + re + ').*$'
|
|
|
|
try {
|
|
this.regexp = new RegExp(re, flags)
|
|
} catch (ex) {
|
|
this.regexp = false
|
|
}
|
|
return this.regexp
|
|
}
|
|
|
|
minimatch.match = function (list, pattern, options) {
|
|
options = options || {}
|
|
var mm = new Minimatch(pattern, options)
|
|
list = list.filter(function (f) {
|
|
return mm.match(f)
|
|
})
|
|
if (mm.options.nonull && !list.length) {
|
|
list.push(pattern)
|
|
}
|
|
return list
|
|
}
|
|
|
|
Minimatch.prototype.match = match
|
|
function match (f, partial) {
|
|
this.debug('match', f, this.pattern)
|
|
// short-circuit in the case of busted things.
|
|
// comments, etc.
|
|
if (this.comment) return false
|
|
if (this.empty) return f === ''
|
|
|
|
if (f === '/' && partial) return true
|
|
|
|
var options = this.options
|
|
|
|
// windows: need to use /, not \
|
|
if (path.sep !== '/') {
|
|
f = f.split(path.sep).join('/')
|
|
}
|
|
|
|
// treat the test path as a set of pathparts.
|
|
f = f.split(slashSplit)
|
|
this.debug(this.pattern, 'split', f)
|
|
|
|
// just ONE of the pattern sets in this.set needs to match
|
|
// in order for it to be valid. If negating, then just one
|
|
// match means that we have failed.
|
|
// Either way, return on the first hit.
|
|
|
|
var set = this.set
|
|
this.debug(this.pattern, 'set', set)
|
|
|
|
// Find the basename of the path by looking for the last non-empty segment
|
|
var filename
|
|
var i
|
|
for (i = f.length - 1; i >= 0; i--) {
|
|
filename = f[i]
|
|
if (filename) break
|
|
}
|
|
|
|
for (i = 0; i < set.length; i++) {
|
|
var pattern = set[i]
|
|
var file = f
|
|
if (options.matchBase && pattern.length === 1) {
|
|
file = [filename]
|
|
}
|
|
var hit = this.matchOne(file, pattern, partial)
|
|
if (hit) {
|
|
if (options.flipNegate) return true
|
|
return !this.negate
|
|
}
|
|
}
|
|
|
|
// didn't get any hits. this is success if it's a negative
|
|
// pattern, failure otherwise.
|
|
if (options.flipNegate) return false
|
|
return this.negate
|
|
}
|
|
|
|
// set partial to true to test if, for example,
|
|
// "/a/b" matches the start of "/*/b/*/d"
|
|
// Partial means, if you run out of file before you run
|
|
// out of pattern, then that's fine, as long as all
|
|
// the parts match.
|
|
Minimatch.prototype.matchOne = function (file, pattern, partial) {
|
|
var options = this.options
|
|
|
|
this.debug('matchOne',
|
|
{ 'this': this, file: file, pattern: pattern })
|
|
|
|
this.debug('matchOne', file.length, pattern.length)
|
|
|
|
for (var fi = 0,
|
|
pi = 0,
|
|
fl = file.length,
|
|
pl = pattern.length
|
|
; (fi < fl) && (pi < pl)
|
|
; fi++, pi++) {
|
|
this.debug('matchOne loop')
|
|
var p = pattern[pi]
|
|
var f = file[fi]
|
|
|
|
this.debug(pattern, p, f)
|
|
|
|
// should be impossible.
|
|
// some invalid regexp stuff in the set.
|
|
if (p === false) return false
|
|
|
|
if (p === GLOBSTAR) {
|
|
this.debug('GLOBSTAR', [pattern, p, f])
|
|
|
|
// "**"
|
|
// a/**/b/**/c would match the following:
|
|
// a/b/x/y/z/c
|
|
// a/x/y/z/b/c
|
|
// a/b/x/b/x/c
|
|
// a/b/c
|
|
// To do this, take the rest of the pattern after
|
|
// the **, and see if it would match the file remainder.
|
|
// If so, return success.
|
|
// If not, the ** "swallows" a segment, and try again.
|
|
// This is recursively awful.
|
|
//
|
|
// a/**/b/**/c matching a/b/x/y/z/c
|
|
// - a matches a
|
|
// - doublestar
|
|
// - matchOne(b/x/y/z/c, b/**/c)
|
|
// - b matches b
|
|
// - doublestar
|
|
// - matchOne(x/y/z/c, c) -> no
|
|
// - matchOne(y/z/c, c) -> no
|
|
// - matchOne(z/c, c) -> no
|
|
// - matchOne(c, c) yes, hit
|
|
var fr = fi
|
|
var pr = pi + 1
|
|
if (pr === pl) {
|
|
this.debug('** at the end')
|
|
// a ** at the end will just swallow the rest.
|
|
// We have found a match.
|
|
// however, it will not swallow /.x, unless
|
|
// options.dot is set.
|
|
// . and .. are *never* matched by **, for explosively
|
|
// exponential reasons.
|
|
for (; fi < fl; fi++) {
|
|
if (file[fi] === '.' || file[fi] === '..' ||
|
|
(!options.dot && file[fi].charAt(0) === '.')) return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// ok, let's see if we can swallow whatever we can.
|
|
while (fr < fl) {
|
|
var swallowee = file[fr]
|
|
|
|
this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
|
|
|
|
// XXX remove this slice. Just pass the start index.
|
|
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
|
|
this.debug('globstar found match!', fr, fl, swallowee)
|
|
// found a match.
|
|
return true
|
|
} else {
|
|
// can't swallow "." or ".." ever.
|
|
// can only swallow ".foo" when explicitly asked.
|
|
if (swallowee === '.' || swallowee === '..' ||
|
|
(!options.dot && swallowee.charAt(0) === '.')) {
|
|
this.debug('dot detected!', file, fr, pattern, pr)
|
|
break
|
|
}
|
|
|
|
// ** swallows a segment, and continue.
|
|
this.debug('globstar swallow a segment, and continue')
|
|
fr++
|
|
}
|
|
}
|
|
|
|
// no match was found.
|
|
// However, in partial mode, we can't say this is necessarily over.
|
|
// If there's more *pattern* left, then
|
|
if (partial) {
|
|
// ran out of file
|
|
this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
|
|
if (fr === fl) return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// something other than **
|
|
// non-magic patterns just have to match exactly
|
|
// patterns with magic have been turned into regexps.
|
|
var hit
|
|
if (typeof p === 'string') {
|
|
if (options.nocase) {
|
|
hit = f.toLowerCase() === p.toLowerCase()
|
|
} else {
|
|
hit = f === p
|
|
}
|
|
this.debug('string match', p, f, hit)
|
|
} else {
|
|
hit = f.match(p)
|
|
this.debug('pattern match', p, f, hit)
|
|
}
|
|
|
|
if (!hit) return false
|
|
}
|
|
|
|
// Note: ending in / means that we'll get a final ""
|
|
// at the end of the pattern. This can only match a
|
|
// corresponding "" at the end of the file.
|
|
// If the file ends in /, then it can only match a
|
|
// a pattern that ends in /, unless the pattern just
|
|
// doesn't have any more for it. But, a/b/ should *not*
|
|
// match "a/b/*", even though "" matches against the
|
|
// [^/]*? pattern, except in partial mode, where it might
|
|
// simply not be reached yet.
|
|
// However, a/b/ should still satisfy a/*
|
|
|
|
// now either we fell off the end of the pattern, or we're done.
|
|
if (fi === fl && pi === pl) {
|
|
// ran out of pattern and filename at the same time.
|
|
// an exact hit!
|
|
return true
|
|
} else if (fi === fl) {
|
|
// ran out of file, but still had pattern left.
|
|
// this is ok if we're doing the match as part of
|
|
// a glob fs traversal.
|
|
return partial
|
|
} else if (pi === pl) {
|
|
// ran out of pattern, still have file left.
|
|
// this is only acceptable if we're on the very last
|
|
// empty segment of a file with a trailing slash.
|
|
// a/* should match a/b/
|
|
var emptyFileEnd = (fi === fl - 1) && (file[fi] === '')
|
|
return emptyFileEnd
|
|
}
|
|
|
|
// should be unreachable.
|
|
throw new Error('wtf?')
|
|
}
|
|
|
|
// replace stuff like \* with *
|
|
function globUnescape (s) {
|
|
return s.replace(/\\(.)/g, '$1')
|
|
}
|
|
|
|
function regExpEscape (s) {
|
|
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 202 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var concatMap = __webpack_require__(203);
|
|
var balanced = __webpack_require__(204);
|
|
|
|
module.exports = expandTop;
|
|
|
|
var escSlash = '\0SLASH'+Math.random()+'\0';
|
|
var escOpen = '\0OPEN'+Math.random()+'\0';
|
|
var escClose = '\0CLOSE'+Math.random()+'\0';
|
|
var escComma = '\0COMMA'+Math.random()+'\0';
|
|
var escPeriod = '\0PERIOD'+Math.random()+'\0';
|
|
|
|
function numeric(str) {
|
|
return parseInt(str, 10) == str
|
|
? parseInt(str, 10)
|
|
: str.charCodeAt(0);
|
|
}
|
|
|
|
function escapeBraces(str) {
|
|
return str.split('\\\\').join(escSlash)
|
|
.split('\\{').join(escOpen)
|
|
.split('\\}').join(escClose)
|
|
.split('\\,').join(escComma)
|
|
.split('\\.').join(escPeriod);
|
|
}
|
|
|
|
function unescapeBraces(str) {
|
|
return str.split(escSlash).join('\\')
|
|
.split(escOpen).join('{')
|
|
.split(escClose).join('}')
|
|
.split(escComma).join(',')
|
|
.split(escPeriod).join('.');
|
|
}
|
|
|
|
|
|
// Basically just str.split(","), but handling cases
|
|
// where we have nested braced sections, which should be
|
|
// treated as individual members, like {a,{b,c},d}
|
|
function parseCommaParts(str) {
|
|
if (!str)
|
|
return [''];
|
|
|
|
var parts = [];
|
|
var m = balanced('{', '}', str);
|
|
|
|
if (!m)
|
|
return str.split(',');
|
|
|
|
var pre = m.pre;
|
|
var body = m.body;
|
|
var post = m.post;
|
|
var p = pre.split(',');
|
|
|
|
p[p.length-1] += '{' + body + '}';
|
|
var postParts = parseCommaParts(post);
|
|
if (post.length) {
|
|
p[p.length-1] += postParts.shift();
|
|
p.push.apply(p, postParts);
|
|
}
|
|
|
|
parts.push.apply(parts, p);
|
|
|
|
return parts;
|
|
}
|
|
|
|
function expandTop(str) {
|
|
if (!str)
|
|
return [];
|
|
|
|
// I don't know why Bash 4.3 does this, but it does.
|
|
// Anything starting with {} will have the first two bytes preserved
|
|
// but *only* at the top level, so {},a}b will not expand to anything,
|
|
// but a{},b}c will be expanded to [a}c,abc].
|
|
// One could argue that this is a bug in Bash, but since the goal of
|
|
// this module is to match Bash's rules, we escape a leading {}
|
|
if (str.substr(0, 2) === '{}') {
|
|
str = '\\{\\}' + str.substr(2);
|
|
}
|
|
|
|
return expand(escapeBraces(str), true).map(unescapeBraces);
|
|
}
|
|
|
|
function identity(e) {
|
|
return e;
|
|
}
|
|
|
|
function embrace(str) {
|
|
return '{' + str + '}';
|
|
}
|
|
function isPadded(el) {
|
|
return /^-?0\d/.test(el);
|
|
}
|
|
|
|
function lte(i, y) {
|
|
return i <= y;
|
|
}
|
|
function gte(i, y) {
|
|
return i >= y;
|
|
}
|
|
|
|
function expand(str, isTop) {
|
|
var expansions = [];
|
|
|
|
var m = balanced('{', '}', str);
|
|
if (!m || /\$$/.test(m.pre)) return [str];
|
|
|
|
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
|
|
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
|
|
var isSequence = isNumericSequence || isAlphaSequence;
|
|
var isOptions = m.body.indexOf(',') >= 0;
|
|
if (!isSequence && !isOptions) {
|
|
// {a},b}
|
|
if (m.post.match(/,.*\}/)) {
|
|
str = m.pre + '{' + m.body + escClose + m.post;
|
|
return expand(str);
|
|
}
|
|
return [str];
|
|
}
|
|
|
|
var n;
|
|
if (isSequence) {
|
|
n = m.body.split(/\.\./);
|
|
} else {
|
|
n = parseCommaParts(m.body);
|
|
if (n.length === 1) {
|
|
// x{{a,b}}y ==> x{a}y x{b}y
|
|
n = expand(n[0], false).map(embrace);
|
|
if (n.length === 1) {
|
|
var post = m.post.length
|
|
? expand(m.post, false)
|
|
: [''];
|
|
return post.map(function(p) {
|
|
return m.pre + n[0] + p;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// at this point, n is the parts, and we know it's not a comma set
|
|
// with a single entry.
|
|
|
|
// no need to expand pre, since it is guaranteed to be free of brace-sets
|
|
var pre = m.pre;
|
|
var post = m.post.length
|
|
? expand(m.post, false)
|
|
: [''];
|
|
|
|
var N;
|
|
|
|
if (isSequence) {
|
|
var x = numeric(n[0]);
|
|
var y = numeric(n[1]);
|
|
var width = Math.max(n[0].length, n[1].length)
|
|
var incr = n.length == 3
|
|
? Math.abs(numeric(n[2]))
|
|
: 1;
|
|
var test = lte;
|
|
var reverse = y < x;
|
|
if (reverse) {
|
|
incr *= -1;
|
|
test = gte;
|
|
}
|
|
var pad = n.some(isPadded);
|
|
|
|
N = [];
|
|
|
|
for (var i = x; test(i, y); i += incr) {
|
|
var c;
|
|
if (isAlphaSequence) {
|
|
c = String.fromCharCode(i);
|
|
if (c === '\\')
|
|
c = '';
|
|
} else {
|
|
c = String(i);
|
|
if (pad) {
|
|
var need = width - c.length;
|
|
if (need > 0) {
|
|
var z = new Array(need + 1).join('0');
|
|
if (i < 0)
|
|
c = '-' + z + c.slice(1);
|
|
else
|
|
c = z + c;
|
|
}
|
|
}
|
|
}
|
|
N.push(c);
|
|
}
|
|
} else {
|
|
N = concatMap(n, function(el) { return expand(el, false) });
|
|
}
|
|
|
|
for (var j = 0; j < N.length; j++) {
|
|
for (var k = 0; k < post.length; k++) {
|
|
var expansion = pre + N[j] + post[k];
|
|
if (!isTop || isSequence || expansion)
|
|
expansions.push(expansion);
|
|
}
|
|
}
|
|
|
|
return expansions;
|
|
}
|
|
|
|
|
|
|
|
/***/ }),
|
|
/* 203 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = function (xs, fn) {
|
|
var res = [];
|
|
for (var i = 0; i < xs.length; i++) {
|
|
var x = fn(xs[i], i);
|
|
if (isArray(x)) res.push.apply(res, x);
|
|
else res.push(x);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
var isArray = Array.isArray || function (xs) {
|
|
return Object.prototype.toString.call(xs) === '[object Array]';
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 204 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
module.exports = balanced;
|
|
function balanced(a, b, str) {
|
|
if (a instanceof RegExp) a = maybeMatch(a, str);
|
|
if (b instanceof RegExp) b = maybeMatch(b, str);
|
|
|
|
var r = range(a, b, str);
|
|
|
|
return r && {
|
|
start: r[0],
|
|
end: r[1],
|
|
pre: str.slice(0, r[0]),
|
|
body: str.slice(r[0] + a.length, r[1]),
|
|
post: str.slice(r[1] + b.length)
|
|
};
|
|
}
|
|
|
|
function maybeMatch(reg, str) {
|
|
var m = str.match(reg);
|
|
return m ? m[0] : null;
|
|
}
|
|
|
|
balanced.range = range;
|
|
function range(a, b, str) {
|
|
var begs, beg, left, right, result;
|
|
var ai = str.indexOf(a);
|
|
var bi = str.indexOf(b, ai + 1);
|
|
var i = ai;
|
|
|
|
if (ai >= 0 && bi > 0) {
|
|
begs = [];
|
|
left = str.length;
|
|
|
|
while (i >= 0 && !result) {
|
|
if (i == ai) {
|
|
begs.push(i);
|
|
ai = str.indexOf(a, i + 1);
|
|
} else if (begs.length == 1) {
|
|
result = [ begs.pop(), bi ];
|
|
} else {
|
|
beg = begs.pop();
|
|
if (beg < left) {
|
|
left = beg;
|
|
right = bi;
|
|
}
|
|
|
|
bi = str.indexOf(b, i + 1);
|
|
}
|
|
|
|
i = ai < bi && ai >= 0 ? ai : bi;
|
|
}
|
|
|
|
if (begs.length) {
|
|
result = [ left, right ];
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 205 */
|
|
/***/ (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__(55));
|
|
const jsonc_parser_1 = __webpack_require__(195);
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const logger = __webpack_require__(186)('configuration-shape');
|
|
class ConfigurationProxy {
|
|
constructor(workspace) {
|
|
this.workspace = workspace;
|
|
}
|
|
get nvim() {
|
|
return this.workspace.nvim;
|
|
}
|
|
async modifyConfiguration(target, key, value) {
|
|
let { nvim, workspace } = this;
|
|
let file = workspace.getConfigFile(target);
|
|
if (!file)
|
|
return;
|
|
let formattingOptions = { tabSize: 2, insertSpaces: true };
|
|
let content = fs_1.default.readFileSync(file, 'utf8');
|
|
value = value == null ? undefined : value;
|
|
let edits = jsonc_parser_1.modify(content, [key], value, { formattingOptions });
|
|
content = jsonc_parser_1.applyEdits(content, edits);
|
|
fs_1.default.writeFileSync(file, content, 'utf8');
|
|
let doc = workspace.getDocument(vscode_uri_1.URI.file(file).toString());
|
|
if (doc)
|
|
nvim.command('checktime', true);
|
|
return;
|
|
}
|
|
get workspaceConfigFile() {
|
|
let folder = path_1.default.join(this.workspace.root, '.vim');
|
|
return path_1.default.join(folder, 'coc-settings.json');
|
|
}
|
|
$updateConfigurationOption(target, key, value) {
|
|
this.modifyConfiguration(target, key, value); // tslint:disable-line
|
|
}
|
|
$removeConfigurationOption(target, key) {
|
|
this.modifyConfiguration(target, key); // tslint:disable-line
|
|
}
|
|
}
|
|
exports.default = ConfigurationProxy;
|
|
//# sourceMappingURL=shape.js.map
|
|
|
|
/***/ }),
|
|
/* 206 */
|
|
/***/ (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__(55));
|
|
const mkdirp_1 = tslib_1.__importDefault(__webpack_require__(179));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
class DB {
|
|
constructor(filepath) {
|
|
this.filepath = filepath;
|
|
}
|
|
/**
|
|
* Get data by key.
|
|
*
|
|
* @param {string} key unique key allows dot notation.
|
|
* @returns {any}
|
|
*/
|
|
fetch(key) {
|
|
let obj = this.load();
|
|
if (!key)
|
|
return obj;
|
|
let parts = key.split('.');
|
|
for (let part of parts) {
|
|
if (typeof obj[part] == 'undefined') {
|
|
return undefined;
|
|
}
|
|
obj = obj[part];
|
|
}
|
|
return obj;
|
|
}
|
|
/**
|
|
* Check if key exists
|
|
*
|
|
* @param {string} key unique key allows dot notation.
|
|
*/
|
|
exists(key) {
|
|
let obj = this.load();
|
|
let parts = key.split('.');
|
|
for (let part of parts) {
|
|
if (typeof obj[part] == 'undefined') {
|
|
return false;
|
|
}
|
|
obj = obj[part];
|
|
}
|
|
return true;
|
|
}
|
|
/**
|
|
* Delete data by key
|
|
*
|
|
* @param {string} key unique key allows dot notation.
|
|
*/
|
|
delete(key) {
|
|
let obj = this.load();
|
|
let origin = obj;
|
|
let parts = key.split('.');
|
|
let len = parts.length;
|
|
for (let i = 0; i < len; i++) {
|
|
if (typeof obj[parts[i]] == 'undefined') {
|
|
break;
|
|
}
|
|
if (i == len - 1) {
|
|
delete obj[parts[i]];
|
|
fs_1.default.writeFileSync(this.filepath, JSON.stringify(origin, null, 2), 'utf8');
|
|
break;
|
|
}
|
|
obj = obj[parts[i]];
|
|
}
|
|
}
|
|
/**
|
|
* Save data with key
|
|
*
|
|
* @param {string} key unique string that allows dot notation.
|
|
* @param {number|null|boolean|string|{[index} data saved data.
|
|
*/
|
|
push(key, data) {
|
|
let origin = this.load() || {};
|
|
let obj = origin;
|
|
let parts = key.split('.');
|
|
let len = parts.length;
|
|
if (obj == null) {
|
|
let dir = path_1.default.dirname(this.filepath);
|
|
mkdirp_1.default.sync(dir);
|
|
obj = origin;
|
|
}
|
|
for (let i = 0; i < len; i++) {
|
|
let key = parts[i];
|
|
if (i == len - 1) {
|
|
obj[key] = data;
|
|
fs_1.default.writeFileSync(this.filepath, JSON.stringify(origin, null, 2));
|
|
break;
|
|
}
|
|
if (typeof obj[key] == 'undefined') {
|
|
obj[key] = {};
|
|
obj = obj[key];
|
|
}
|
|
else {
|
|
obj = obj[key];
|
|
}
|
|
}
|
|
}
|
|
load() {
|
|
let dir = path_1.default.dirname(this.filepath);
|
|
let stat = fs_1.default.statSync(dir);
|
|
if (!stat || !stat.isDirectory()) {
|
|
mkdirp_1.default.sync(dir);
|
|
fs_1.default.writeFileSync(this.filepath, '{}', 'utf8');
|
|
return {};
|
|
}
|
|
try {
|
|
let content = fs_1.default.readFileSync(this.filepath, 'utf8');
|
|
return JSON.parse(content.trim());
|
|
}
|
|
catch (e) {
|
|
fs_1.default.writeFileSync(this.filepath, '{}', 'utf8');
|
|
return {};
|
|
}
|
|
}
|
|
/**
|
|
* Empty db file.
|
|
*/
|
|
clear() {
|
|
let stat = fs_1.default.statSync(this.filepath);
|
|
if (!stat || !stat.isFile())
|
|
return;
|
|
fs_1.default.writeFileSync(this.filepath, '{}', 'utf8');
|
|
}
|
|
/**
|
|
* Remove db file.
|
|
*/
|
|
destroy() {
|
|
if (fs_1.default.existsSync(this.filepath)) {
|
|
fs_1.default.unlinkSync(this.filepath);
|
|
}
|
|
}
|
|
}
|
|
exports.default = DB;
|
|
//# sourceMappingURL=db.js.map
|
|
|
|
/***/ }),
|
|
/* 207 */
|
|
/***/ (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__(176));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const diff_1 = __webpack_require__(208);
|
|
const fs_1 = __webpack_require__(200);
|
|
const index_1 = __webpack_require__(174);
|
|
const string_1 = __webpack_require__(210);
|
|
const chars_1 = __webpack_require__(211);
|
|
const array_1 = __webpack_require__(212);
|
|
const position_1 = __webpack_require__(213);
|
|
const logger = __webpack_require__(186)('model-document');
|
|
// wrapper class of TextDocument
|
|
class Document {
|
|
constructor(buffer, env) {
|
|
this.buffer = buffer;
|
|
this.env = env;
|
|
this.paused = false;
|
|
this.isIgnored = false;
|
|
// start id for matchaddpos
|
|
this.colorId = 1080;
|
|
this.eol = true;
|
|
this.attached = false;
|
|
// real current lines
|
|
this.lines = [];
|
|
this._words = [];
|
|
this._onDocumentChange = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDocumentDetach = new vscode_languageserver_protocol_1.Emitter();
|
|
this.onDocumentChange = this._onDocumentChange.event;
|
|
this.onDocumentDetach = this._onDocumentDetach.event;
|
|
this.fireContentChanges = debounce_1.default(() => {
|
|
this.nvim.mode.then(m => {
|
|
if (m.blocking) {
|
|
this.fireContentChanges();
|
|
return;
|
|
}
|
|
this._fireContentChanges();
|
|
}).logError();
|
|
}, 200);
|
|
this.fetchContent = debounce_1.default(() => {
|
|
this._fetchContent().logError();
|
|
}, 50);
|
|
}
|
|
/**
|
|
* Check if current document should be attached for changes.
|
|
*
|
|
* Currently only attach for empty and `acwrite` buftype.
|
|
*/
|
|
get shouldAttach() {
|
|
let { buftype } = this;
|
|
if (!this.getVar('enabled', true))
|
|
return false;
|
|
if (this.uri.endsWith('%5BCommand%20Line%5D'))
|
|
return true;
|
|
return buftype == '' || buftype == 'acwrite';
|
|
}
|
|
get enabled() {
|
|
return this.getVar('enabled', true);
|
|
}
|
|
/**
|
|
* All words, extracted by `iskeyword` option.
|
|
*/
|
|
get words() {
|
|
return this._words;
|
|
}
|
|
/**
|
|
* Map filetype for languageserver.
|
|
*/
|
|
convertFiletype(filetype) {
|
|
let map = this.env.filetypeMap;
|
|
if (filetype == 'json' && this.uri && this.uri.endsWith('coc-settings.json')) {
|
|
return 'jsonc';
|
|
}
|
|
if (filetype == 'javascript.jsx')
|
|
return 'javascriptreact';
|
|
if (filetype == 'typescript.jsx' || filetype == 'typescript.tsx')
|
|
return 'typescriptreact';
|
|
return map[filetype] || filetype;
|
|
}
|
|
/**
|
|
* Get current buffer changedtick.
|
|
*/
|
|
get changedtick() {
|
|
return this._changedtick;
|
|
}
|
|
/**
|
|
* Scheme of document.
|
|
*/
|
|
get schema() {
|
|
return vscode_uri_1.URI.parse(this.uri).scheme;
|
|
}
|
|
/**
|
|
* Line count of current buffer.
|
|
*/
|
|
get lineCount() {
|
|
return this.lines.length;
|
|
}
|
|
/**
|
|
* Initialize document model.
|
|
*
|
|
* @internal
|
|
*/
|
|
async init(nvim, token) {
|
|
this.nvim = nvim;
|
|
let { buffer } = this;
|
|
let opts = await nvim.call('coc#util#get_bufoptions', buffer.id);
|
|
if (opts == null)
|
|
return false;
|
|
let buftype = this.buftype = opts.buftype;
|
|
this.variables = opts.variables;
|
|
this._changedtick = opts.changedtick;
|
|
this.eol = opts.eol == 1;
|
|
let uri = this._uri = index_1.getUri(opts.fullpath, buffer.id, buftype, this.env.isCygwin);
|
|
if (token.isCancellationRequested)
|
|
return false;
|
|
try {
|
|
if (!this.env.isVim) {
|
|
let res = await this.attach();
|
|
if (!res)
|
|
return false;
|
|
}
|
|
else {
|
|
this.lines = await buffer.lines;
|
|
}
|
|
this.attached = true;
|
|
}
|
|
catch (e) {
|
|
logger.error('attach error:', e);
|
|
return false;
|
|
}
|
|
this._filetype = this.convertFiletype(opts.filetype);
|
|
this.textDocument = vscode_languageserver_protocol_1.TextDocument.create(uri, this.filetype, 1, this.getDocumentContent());
|
|
this.setIskeyword(opts.iskeyword);
|
|
this.gitCheck();
|
|
if (token.isCancellationRequested) {
|
|
this.detach();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
async attach() {
|
|
if (this.shouldAttach) {
|
|
let attached = await this.buffer.attach(false);
|
|
if (!attached)
|
|
return false;
|
|
this.lines = await this.buffer.lines;
|
|
}
|
|
else {
|
|
this.lines = await this.buffer.lines;
|
|
return true;
|
|
}
|
|
if (!this.buffer.isAttached)
|
|
return;
|
|
this.buffer.listen('lines', (...args) => {
|
|
this.onChange.apply(this, args);
|
|
});
|
|
this.buffer.listen('detach', async () => {
|
|
await index_1.wait(30);
|
|
if (!this.attached)
|
|
return;
|
|
// it could be detached by `edit!`
|
|
let attached = await this.attach();
|
|
if (!attached)
|
|
this.detach();
|
|
});
|
|
this.buffer.listen('changedtick', (_buf, tick) => {
|
|
this._changedtick = tick;
|
|
});
|
|
if (this.textDocument) {
|
|
this.fireContentChanges();
|
|
}
|
|
return true;
|
|
}
|
|
onChange(buf, tick, firstline, lastline, linedata
|
|
// more:boolean
|
|
) {
|
|
if (buf.id !== this.buffer.id || tick == null)
|
|
return;
|
|
this._changedtick = tick;
|
|
let lines = this.lines.slice(0, firstline);
|
|
lines = lines.concat(linedata, this.lines.slice(lastline));
|
|
this.lines = lines;
|
|
this.fireContentChanges();
|
|
}
|
|
/**
|
|
* Make sure current document synced correctly
|
|
*/
|
|
async checkDocument() {
|
|
this.paused = false;
|
|
let { buffer } = this;
|
|
this._changedtick = await buffer.changedtick;
|
|
this.lines = await buffer.lines;
|
|
this.fireContentChanges.clear();
|
|
this._fireContentChanges();
|
|
}
|
|
/**
|
|
* Check if document changed after last synchronize
|
|
*/
|
|
get dirty() {
|
|
return this.content != this.getDocumentContent();
|
|
}
|
|
_fireContentChanges(force = false) {
|
|
let { paused, textDocument } = this;
|
|
if (paused && !force)
|
|
return;
|
|
let { cursor } = events_1.default;
|
|
try {
|
|
let content = this.getDocumentContent();
|
|
let endOffset = null;
|
|
if (cursor && cursor.bufnr == this.bufnr) {
|
|
endOffset = this.getEndOffset(cursor.lnum, cursor.col, cursor.insert);
|
|
if (!cursor.insert && content.length < this.content.length) {
|
|
endOffset = endOffset + 1;
|
|
}
|
|
}
|
|
let change = diff_1.getChange(this.content, content, endOffset);
|
|
if (change == null)
|
|
return;
|
|
this.createDocument();
|
|
let { version, uri } = this;
|
|
let start = textDocument.positionAt(change.start);
|
|
let end = textDocument.positionAt(change.end);
|
|
let original = textDocument.getText(vscode_languageserver_protocol_1.Range.create(start, end));
|
|
let changes = [{
|
|
range: { start, end },
|
|
rangeLength: change.end - change.start,
|
|
text: change.newText
|
|
}];
|
|
this._onDocumentChange.fire({
|
|
bufnr: this.bufnr,
|
|
original,
|
|
textDocument: { version, uri },
|
|
contentChanges: changes
|
|
});
|
|
this._words = this.chars.matchKeywords(this.lines.join('\n'));
|
|
}
|
|
catch (e) {
|
|
logger.error(e.message);
|
|
}
|
|
}
|
|
/**
|
|
* Buffer number
|
|
*/
|
|
get bufnr() {
|
|
return this.buffer.id;
|
|
}
|
|
/**
|
|
* Content of textDocument.
|
|
*/
|
|
get content() {
|
|
return this.textDocument.getText();
|
|
}
|
|
/**
|
|
* Coverted filetype.
|
|
*/
|
|
get filetype() {
|
|
return this._filetype;
|
|
}
|
|
get uri() {
|
|
return this._uri;
|
|
}
|
|
get version() {
|
|
return this.textDocument ? this.textDocument.version : null;
|
|
}
|
|
async applyEdits(nvim, _edits, sync = true) {
|
|
let edits = [];
|
|
if (Array.isArray(nvim)) {
|
|
sync = _edits == null ? true : _edits;
|
|
edits = nvim;
|
|
}
|
|
else {
|
|
edits = _edits || [];
|
|
}
|
|
if (edits.length == 0)
|
|
return;
|
|
edits.forEach(edit => {
|
|
edit.newText = edit.newText.replace(/\r/g, '');
|
|
});
|
|
let orig = this.lines.join('\n') + (this.eol ? '\n' : '');
|
|
let textDocument = vscode_languageserver_protocol_1.TextDocument.create(this.uri, this.filetype, 1, orig);
|
|
let content = vscode_languageserver_protocol_1.TextDocument.applyEdits(textDocument, edits);
|
|
// could be equal sometimes
|
|
if (orig === content) {
|
|
this.createDocument();
|
|
}
|
|
else {
|
|
let d = diff_1.diffLines(orig, content);
|
|
await this.buffer.setLines(d.replacement, {
|
|
start: d.start,
|
|
end: d.end,
|
|
strictIndexing: false
|
|
});
|
|
// can't wait vim sync buffer
|
|
this.lines = (this.eol && content.endsWith('\n') ? content.slice(0, -1) : content).split('\n');
|
|
if (sync)
|
|
this.forceSync();
|
|
}
|
|
}
|
|
changeLines(lines, sync = true, check = false) {
|
|
let { nvim } = this;
|
|
let filtered = [];
|
|
for (let [lnum, text] of lines) {
|
|
if (check && this.lines[lnum] != text) {
|
|
filtered.push([lnum, text]);
|
|
}
|
|
this.lines[lnum] = text;
|
|
}
|
|
if (check && !filtered.length)
|
|
return;
|
|
nvim.call('coc#util#change_lines', [this.bufnr, check ? filtered : lines], true);
|
|
if (sync)
|
|
this.forceSync();
|
|
}
|
|
/**
|
|
* Force emit change event when necessary.
|
|
*/
|
|
forceSync(ignorePause = true) {
|
|
this.fireContentChanges.clear();
|
|
this._fireContentChanges(ignorePause);
|
|
}
|
|
/**
|
|
* Get offset from lnum & col
|
|
*/
|
|
getOffset(lnum, col) {
|
|
return this.textDocument.offsetAt({
|
|
line: lnum - 1,
|
|
character: col
|
|
});
|
|
}
|
|
/**
|
|
* Check string is word.
|
|
*/
|
|
isWord(word) {
|
|
return this.chars.isKeyword(word);
|
|
}
|
|
/**
|
|
* Generate more words by split word with `-`
|
|
*/
|
|
getMoreWords() {
|
|
let res = [];
|
|
let { words, chars } = this;
|
|
if (!chars.isKeywordChar('-'))
|
|
return res;
|
|
for (let word of words) {
|
|
word = word.replace(/^-+/, '');
|
|
if (word.indexOf('-') !== -1) {
|
|
let parts = word.split('-');
|
|
for (let part of parts) {
|
|
if (part.length > 2 &&
|
|
res.indexOf(part) === -1 &&
|
|
words.indexOf(part) === -1) {
|
|
res.push(part);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
/**
|
|
* Current word for replacement
|
|
*/
|
|
getWordRangeAtPosition(position, extraChars, current = true) {
|
|
let chars = this.chars.clone();
|
|
if (extraChars && extraChars.length) {
|
|
for (let ch of extraChars) {
|
|
chars.addKeyword(ch);
|
|
}
|
|
}
|
|
let line = this.getline(position.line, current);
|
|
if (line.length == 0 || position.character >= line.length)
|
|
return null;
|
|
if (!chars.isKeywordChar(line[position.character]))
|
|
return null;
|
|
let start = position.character;
|
|
let end = position.character + 1;
|
|
if (!chars.isKeywordChar(line[start])) {
|
|
return vscode_languageserver_protocol_1.Range.create(position, { line: position.line, character: position.character + 1 });
|
|
}
|
|
while (start >= 0) {
|
|
let ch = line[start - 1];
|
|
if (!ch || !chars.isKeyword(ch))
|
|
break;
|
|
start = start - 1;
|
|
}
|
|
while (end <= line.length) {
|
|
let ch = line[end];
|
|
if (!ch || !chars.isKeywordChar(ch))
|
|
break;
|
|
end = end + 1;
|
|
}
|
|
return vscode_languageserver_protocol_1.Range.create(position.line, start, position.line, end);
|
|
}
|
|
gitCheck() {
|
|
let { uri } = this;
|
|
if (!uri.startsWith('file') || this.buftype != '')
|
|
return;
|
|
let filepath = vscode_uri_1.URI.parse(uri).fsPath;
|
|
fs_1.isGitIgnored(filepath).then(isIgnored => {
|
|
this.isIgnored = isIgnored;
|
|
}, () => {
|
|
this.isIgnored = false;
|
|
});
|
|
}
|
|
createDocument(changeCount = 1) {
|
|
let { version, uri, filetype } = this;
|
|
version = version + changeCount;
|
|
this.textDocument = vscode_languageserver_protocol_1.TextDocument.create(uri, filetype, version, this.getDocumentContent());
|
|
}
|
|
async _fetchContent() {
|
|
if (!this.env.isVim || !this.attached)
|
|
return;
|
|
let { nvim, buffer } = this;
|
|
let { id } = buffer;
|
|
let o = (await nvim.call('coc#util#get_content', id));
|
|
if (!o)
|
|
return;
|
|
let { content, changedtick } = o;
|
|
this._changedtick = changedtick;
|
|
let newLines = content.split('\n');
|
|
this.lines = newLines;
|
|
this._fireContentChanges();
|
|
}
|
|
/**
|
|
* Get change from vim8, used by workspace
|
|
*/
|
|
async patchChange() {
|
|
if (!this.env.isVim || !this.attached)
|
|
return;
|
|
let change = await this.nvim.call('coc#util#get_changeinfo', []);
|
|
if (change.changedtick == this._changedtick)
|
|
return;
|
|
let { lines } = this;
|
|
let { lnum, line, changedtick } = change;
|
|
this._changedtick = changedtick;
|
|
lines[lnum - 1] = line;
|
|
}
|
|
/**
|
|
* Get changedtick from vim8, used by workspace
|
|
*/
|
|
async patchChangedTick() {
|
|
if (!this.env.isVim || !this.attached)
|
|
return;
|
|
this._changedtick = await this.nvim.call('getbufvar', [this.bufnr, 'changedtick']);
|
|
}
|
|
/**
|
|
* Get ranges of word in textDocument.
|
|
*/
|
|
getSymbolRanges(word) {
|
|
this.forceSync();
|
|
let { textDocument } = this;
|
|
let res = [];
|
|
let content = textDocument.getText();
|
|
let str = '';
|
|
for (let i = 0, l = content.length; i < l; i++) {
|
|
let ch = content[i];
|
|
if ('-' == ch && str.length == 0) {
|
|
continue;
|
|
}
|
|
let isKeyword = this.chars.isKeywordChar(ch);
|
|
if (isKeyword) {
|
|
str = str + ch;
|
|
}
|
|
if (str.length > 0 && !isKeyword && str == word) {
|
|
res.push(vscode_languageserver_protocol_1.Range.create(textDocument.positionAt(i - str.length), textDocument.positionAt(i)));
|
|
}
|
|
if (!isKeyword) {
|
|
str = '';
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
/**
|
|
* Adjust col with new valid character before position.
|
|
*/
|
|
fixStartcol(position, valids) {
|
|
let line = this.getline(position.line);
|
|
if (!line)
|
|
return null;
|
|
let { character } = position;
|
|
let start = line.slice(0, character);
|
|
let col = string_1.byteLength(start);
|
|
let { chars } = this;
|
|
for (let i = start.length - 1; i >= 0; i--) {
|
|
let c = start[i];
|
|
if (c == ' ')
|
|
break;
|
|
if (!chars.isKeywordChar(c) && valids.indexOf(c) === -1) {
|
|
break;
|
|
}
|
|
col = col - string_1.byteLength(c);
|
|
}
|
|
return col;
|
|
}
|
|
/**
|
|
* Use matchaddpos for highlight ranges, must use `redraw` command on vim
|
|
*/
|
|
matchAddRanges(ranges, hlGroup, priority = 10) {
|
|
let res = [];
|
|
let arr = [];
|
|
let splited = ranges.reduce((p, c) => {
|
|
for (let i = c.start.line; i <= c.end.line; i++) {
|
|
let curr = this.getline(i) || '';
|
|
let sc = i == c.start.line ? c.start.character : 0;
|
|
let ec = i == c.end.line ? c.end.character : curr.length;
|
|
if (sc == ec)
|
|
continue;
|
|
p.push(vscode_languageserver_protocol_1.Range.create(i, sc, i, ec));
|
|
}
|
|
return p;
|
|
}, []);
|
|
for (let range of splited) {
|
|
let { start, end } = range;
|
|
let line = this.getline(start.line);
|
|
if (start.character == end.character)
|
|
continue;
|
|
arr.push([start.line + 1, string_1.byteIndex(line, start.character) + 1, string_1.byteLength(line.slice(start.character, end.character))]);
|
|
}
|
|
for (let grouped of array_1.group(arr, 8)) {
|
|
let id = this.colorId;
|
|
this.colorId = this.colorId + 1;
|
|
this.nvim.call('matchaddpos', [hlGroup, grouped, priority, id], true);
|
|
res.push(id);
|
|
}
|
|
this.nvim.call('coc#util#add_matchids', [res], true);
|
|
return res;
|
|
}
|
|
/**
|
|
* Highlight ranges in document, return match id list.
|
|
*
|
|
* Note: match id could by namespace id or vim's match id.
|
|
*/
|
|
highlightRanges(ranges, hlGroup, srcId, priority = 10) {
|
|
let res = [];
|
|
if (this.env.isVim && !this.env.textprop) {
|
|
res = this.matchAddRanges(ranges, hlGroup, priority);
|
|
}
|
|
else {
|
|
let lineRanges = [];
|
|
for (let range of ranges) {
|
|
if (range.start.line == range.end.line) {
|
|
lineRanges.push(range);
|
|
}
|
|
else {
|
|
// split range by lines
|
|
for (let i = range.start.line; i < range.end.line; i++) {
|
|
let line = this.getline(i);
|
|
if (i == range.start.line) {
|
|
lineRanges.push(vscode_languageserver_protocol_1.Range.create(i, range.start.character, i, line.length));
|
|
}
|
|
else if (i == range.end.line) {
|
|
lineRanges.push(vscode_languageserver_protocol_1.Range.create(i, Math.min(line.match(/^\s*/)[0].length, range.end.character), i, range.end.character));
|
|
}
|
|
else {
|
|
lineRanges.push(vscode_languageserver_protocol_1.Range.create(i, Math.min(line.match(/^\s*/)[0].length, line.length), i, line.length));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (let range of lineRanges) {
|
|
let { start, end } = range;
|
|
if (position_1.comparePosition(start, end) == 0)
|
|
continue;
|
|
let line = this.getline(start.line);
|
|
// tslint:disable-next-line: no-floating-promises
|
|
this.buffer.addHighlight({
|
|
hlGroup,
|
|
srcId,
|
|
line: start.line,
|
|
colStart: string_1.byteIndex(line, start.character),
|
|
colEnd: end.line - start.line == 1 && end.character == 0 ? -1 : string_1.byteIndex(line, end.character)
|
|
});
|
|
}
|
|
res.push(srcId);
|
|
}
|
|
return res;
|
|
}
|
|
/**
|
|
* Clear match id list, for vim support namespace, list should be namespace id list.
|
|
*/
|
|
clearMatchIds(ids) {
|
|
if (this.env.isVim && !this.env.textprop) {
|
|
this.nvim.call('coc#util#clearmatches', [Array.from(ids)], true);
|
|
}
|
|
else {
|
|
ids = array_1.distinct(Array.from(ids));
|
|
let hasNamesapce = this.nvim.hasFunction('nvim_create_namespace');
|
|
ids.forEach(id => {
|
|
if (hasNamesapce) {
|
|
this.buffer.clearNamespace(id);
|
|
}
|
|
else {
|
|
this.buffer.clearHighlight({ srcId: id });
|
|
}
|
|
});
|
|
}
|
|
}
|
|
/**
|
|
* Get cwd of this document.
|
|
*/
|
|
async getcwd() {
|
|
let wid = await this.nvim.call('bufwinid', this.buffer.id);
|
|
if (wid == -1)
|
|
return await this.nvim.call('getcwd');
|
|
return await this.nvim.call('getcwd', wid);
|
|
}
|
|
/**
|
|
* Real current line
|
|
*/
|
|
getline(line, current = true) {
|
|
if (current)
|
|
return this.lines[line] || '';
|
|
let lines = this.textDocument.getText().split(/\r?\n/);
|
|
return lines[line] || '';
|
|
}
|
|
/**
|
|
* Get lines, zero indexed, end exclude.
|
|
*/
|
|
getLines(start, end) {
|
|
return this.lines.slice(start, end);
|
|
}
|
|
/**
|
|
* Get current content text.
|
|
*/
|
|
getDocumentContent() {
|
|
let content = this.lines.join('\n');
|
|
return this.eol ? content + '\n' : content;
|
|
}
|
|
/**
|
|
* Get variable value by key, defined by `b:coc_{key}`
|
|
*/
|
|
getVar(key, defaultValue) {
|
|
let val = this.variables[`coc_${key}`];
|
|
return val === undefined ? defaultValue : val;
|
|
}
|
|
/**
|
|
* Get position from lnum & col
|
|
*/
|
|
getPosition(lnum, col) {
|
|
let line = this.getline(lnum - 1);
|
|
if (!line || col == 0)
|
|
return { line: lnum - 1, character: 0 };
|
|
let pre = string_1.byteSlice(line, 0, col - 1);
|
|
return { line: lnum - 1, character: pre.length };
|
|
}
|
|
getEndOffset(lnum, col, insert) {
|
|
let total = 0;
|
|
let len = this.lines.length;
|
|
for (let i = lnum - 1; i < len; i++) {
|
|
let line = this.lines[i];
|
|
if (i == lnum - 1 && line.length) {
|
|
if (!insert && string_1.byteLength(line) >= col)
|
|
col = col + 1;
|
|
total = total + line.slice(string_1.characterIndex(line, col - 1)).length;
|
|
}
|
|
else {
|
|
total = total + line.length;
|
|
}
|
|
if (!this.eol && i == len - 1)
|
|
break;
|
|
total = total + 1;
|
|
}
|
|
return total;
|
|
}
|
|
/**
|
|
* Recreate document with new filetype.
|
|
*
|
|
* @internal
|
|
*/
|
|
setFiletype(filetype) {
|
|
let { uri, version } = this;
|
|
this._filetype = this.convertFiletype(filetype);
|
|
version = version ? version + 1 : 1;
|
|
let textDocument = vscode_languageserver_protocol_1.TextDocument.create(uri, this.filetype, version, this.content);
|
|
this.textDocument = textDocument;
|
|
}
|
|
/**
|
|
* Change iskeyword option of document
|
|
*
|
|
* @internal
|
|
*/
|
|
setIskeyword(iskeyword) {
|
|
let chars = this.chars = new chars_1.Chars(iskeyword);
|
|
let additional = this.getVar('additional_keywords', []);
|
|
if (additional && Array.isArray(additional)) {
|
|
for (let ch of additional) {
|
|
chars.addKeyword(ch);
|
|
}
|
|
}
|
|
let lines = this.lines.length > 30000 ? this.lines.slice(0, 30000) : this.lines;
|
|
this._words = this.chars.matchKeywords(lines.join('\n'));
|
|
}
|
|
/**
|
|
* Detach document.
|
|
*
|
|
* @internal
|
|
*/
|
|
detach() {
|
|
// neovim not detach on `:checktime`
|
|
if (this.attached) {
|
|
this.attached = false;
|
|
this.buffer.detach().catch(_e => {
|
|
// noop
|
|
});
|
|
this._onDocumentDetach.fire(this.uri);
|
|
}
|
|
this.fetchContent.clear();
|
|
this.fireContentChanges.clear();
|
|
this._onDocumentChange.dispose();
|
|
this._onDocumentDetach.dispose();
|
|
}
|
|
/**
|
|
* Get localify bonus map.
|
|
*
|
|
* @internal
|
|
*/
|
|
getLocalifyBonus(sp, ep) {
|
|
let res = new Map();
|
|
let { chars } = this;
|
|
let startLine = Math.max(0, sp.line - 100);
|
|
let endLine = Math.min(this.lineCount, sp.line + 100);
|
|
let content = this.lines.slice(startLine, endLine).join('\n');
|
|
sp = vscode_languageserver_protocol_1.Position.create(sp.line - startLine, sp.character);
|
|
ep = vscode_languageserver_protocol_1.Position.create(ep.line - startLine, ep.character);
|
|
let doc = vscode_languageserver_protocol_1.TextDocument.create(this.uri, this.filetype, 1, content);
|
|
let headCount = doc.offsetAt(sp);
|
|
let len = content.length;
|
|
let tailCount = len - doc.offsetAt(ep);
|
|
let start = 0;
|
|
let preKeyword = false;
|
|
for (let i = 0; i < headCount; i++) {
|
|
let iskeyword = chars.isKeyword(content[i]);
|
|
if (!preKeyword && iskeyword) {
|
|
start = i;
|
|
}
|
|
else if (preKeyword && (!iskeyword || i == headCount - 1)) {
|
|
if (i - start > 1) {
|
|
let str = content.slice(start, i);
|
|
res.set(str, i / headCount);
|
|
}
|
|
}
|
|
preKeyword = iskeyword;
|
|
}
|
|
start = len - tailCount;
|
|
preKeyword = false;
|
|
for (let i = start; i < content.length; i++) {
|
|
let iskeyword = chars.isKeyword(content[i]);
|
|
if (!preKeyword && iskeyword) {
|
|
start = i;
|
|
}
|
|
else if (preKeyword && (!iskeyword || i == len - 1)) {
|
|
if (i - start > 1) {
|
|
let end = i == len - 1 ? i + 1 : i;
|
|
let str = content.slice(start, end);
|
|
let score = res.get(str) || 0;
|
|
res.set(str, Math.max(score, (len - i + (end - start)) / tailCount));
|
|
}
|
|
}
|
|
preKeyword = iskeyword;
|
|
}
|
|
return res;
|
|
}
|
|
}
|
|
exports.default = Document;
|
|
//# sourceMappingURL=document.js.map
|
|
|
|
/***/ }),
|
|
/* 208 */
|
|
/***/ (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__(209));
|
|
const string_1 = __webpack_require__(210);
|
|
const logger = __webpack_require__(186)('util-diff');
|
|
function diffLines(from, to) {
|
|
let newLines = to.split('\n');
|
|
let oldLines = from.split('\n');
|
|
let start = 0;
|
|
let end = oldLines.length;
|
|
let oldLen = end;
|
|
let len = newLines.length;
|
|
for (let i = 0; i <= end; i++) {
|
|
if (newLines[i] !== oldLines[i]) {
|
|
start = i;
|
|
break;
|
|
}
|
|
if (i == end) {
|
|
start = end;
|
|
}
|
|
}
|
|
if (start != newLines.length) {
|
|
let maxRemain = Math.min(end - start, len - start);
|
|
for (let j = 0; j < maxRemain; j++) {
|
|
if (oldLines[oldLen - j - 1] != newLines[len - j - 1]) {
|
|
break;
|
|
}
|
|
end = end - 1;
|
|
}
|
|
}
|
|
return {
|
|
start,
|
|
end,
|
|
replacement: newLines.slice(start, len - (oldLen - end))
|
|
};
|
|
}
|
|
exports.diffLines = diffLines;
|
|
function getChange(oldStr, newStr, cursorEnd) {
|
|
let start = 0;
|
|
let ol = oldStr.length;
|
|
let nl = newStr.length;
|
|
let max = Math.min(ol, nl);
|
|
let newText = '';
|
|
let endOffset = -1;
|
|
let maxEndOffset = -1;
|
|
for (let i = 0; i <= max; i++) {
|
|
if (cursorEnd != null && i == cursorEnd) {
|
|
endOffset = i;
|
|
}
|
|
if (oldStr[ol - i - 1] != newStr[nl - i - 1]) {
|
|
if (endOffset == -1)
|
|
endOffset = i;
|
|
maxEndOffset = i;
|
|
break;
|
|
}
|
|
}
|
|
if (endOffset == -1)
|
|
return null;
|
|
let remain = max - endOffset;
|
|
if (remain == 0) {
|
|
start = 0;
|
|
}
|
|
else {
|
|
for (let i = 0; i <= remain; i++) {
|
|
if (oldStr[i] != newStr[i] || i == remain) {
|
|
start = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (maxEndOffset != -1
|
|
&& maxEndOffset != endOffset
|
|
&& start + maxEndOffset < max) {
|
|
endOffset = maxEndOffset;
|
|
}
|
|
let end = ol - endOffset;
|
|
newText = newStr.slice(start, nl - endOffset);
|
|
if (ol == nl && start == end)
|
|
return null;
|
|
// optimize for add new line(s)
|
|
if (start == end) {
|
|
let pre = start == 0 ? '' : newStr[start - 1];
|
|
if (pre && pre != '\n'
|
|
&& oldStr[start] == '\n'
|
|
&& newText.startsWith('\n')) {
|
|
return { start: start + 1, end: end + 1, newText: newText.slice(1) + '\n' };
|
|
}
|
|
}
|
|
return { start, end, newText };
|
|
}
|
|
exports.getChange = getChange;
|
|
function patchLine(from, to, fill = ' ') {
|
|
if (from == to)
|
|
return to;
|
|
let idx = to.indexOf(from);
|
|
if (idx !== -1)
|
|
return fill.repeat(idx) + from;
|
|
let result = fast_diff_1.default(from, to);
|
|
let str = '';
|
|
for (let item of result) {
|
|
if (item[0] == fast_diff_1.default.DELETE) {
|
|
// not allowed
|
|
return to;
|
|
}
|
|
else if (item[0] == fast_diff_1.default.INSERT) {
|
|
str = str + fill.repeat(string_1.byteLength(item[1]));
|
|
}
|
|
else {
|
|
str = str + item[1];
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
exports.patchLine = patchLine;
|
|
//# sourceMappingURL=diff.js.map
|
|
|
|
/***/ }),
|
|
/* 209 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* This library modifies the diff-patch-match library by Neil Fraser
|
|
* by removing the patch and match functionality and certain advanced
|
|
* options in the diff function. The original license is as follows:
|
|
*
|
|
* ===
|
|
*
|
|
* Diff Match and Patch
|
|
*
|
|
* Copyright 2006 Google Inc.
|
|
* http://code.google.com/p/google-diff-match-patch/
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
|
|
/**
|
|
* The data structure representing a diff is an array of tuples:
|
|
* [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
|
|
* which means: delete 'Hello', add 'Goodbye' and keep ' world.'
|
|
*/
|
|
var DIFF_DELETE = -1;
|
|
var DIFF_INSERT = 1;
|
|
var DIFF_EQUAL = 0;
|
|
|
|
|
|
/**
|
|
* Find the differences between two texts. Simplifies the problem by stripping
|
|
* any common prefix or suffix off the texts before diffing.
|
|
* @param {string} text1 Old string to be diffed.
|
|
* @param {string} text2 New string to be diffed.
|
|
* @param {Int|Object} [cursor_pos] Edit position in text1 or object with more info
|
|
* @return {Array} Array of diff tuples.
|
|
*/
|
|
function diff_main(text1, text2, cursor_pos, _fix_unicode) {
|
|
// Check for equality
|
|
if (text1 === text2) {
|
|
if (text1) {
|
|
return [[DIFF_EQUAL, text1]];
|
|
}
|
|
return [];
|
|
}
|
|
|
|
if (cursor_pos != null) {
|
|
var editdiff = find_cursor_edit_diff(text1, text2, cursor_pos);
|
|
if (editdiff) {
|
|
return editdiff;
|
|
}
|
|
}
|
|
|
|
// Trim off common prefix (speedup).
|
|
var commonlength = diff_commonPrefix(text1, text2);
|
|
var commonprefix = text1.substring(0, commonlength);
|
|
text1 = text1.substring(commonlength);
|
|
text2 = text2.substring(commonlength);
|
|
|
|
// Trim off common suffix (speedup).
|
|
commonlength = diff_commonSuffix(text1, text2);
|
|
var commonsuffix = text1.substring(text1.length - commonlength);
|
|
text1 = text1.substring(0, text1.length - commonlength);
|
|
text2 = text2.substring(0, text2.length - commonlength);
|
|
|
|
// Compute the diff on the middle block.
|
|
var diffs = diff_compute_(text1, text2);
|
|
|
|
// Restore the prefix and suffix.
|
|
if (commonprefix) {
|
|
diffs.unshift([DIFF_EQUAL, commonprefix]);
|
|
}
|
|
if (commonsuffix) {
|
|
diffs.push([DIFF_EQUAL, commonsuffix]);
|
|
}
|
|
diff_cleanupMerge(diffs, _fix_unicode);
|
|
return diffs;
|
|
};
|
|
|
|
|
|
/**
|
|
* Find the differences between two texts. Assumes that the texts do not
|
|
* have any common prefix or suffix.
|
|
* @param {string} text1 Old string to be diffed.
|
|
* @param {string} text2 New string to be diffed.
|
|
* @return {Array} Array of diff tuples.
|
|
*/
|
|
function diff_compute_(text1, text2) {
|
|
var diffs;
|
|
|
|
if (!text1) {
|
|
// Just add some text (speedup).
|
|
return [[DIFF_INSERT, text2]];
|
|
}
|
|
|
|
if (!text2) {
|
|
// Just delete some text (speedup).
|
|
return [[DIFF_DELETE, text1]];
|
|
}
|
|
|
|
var longtext = text1.length > text2.length ? text1 : text2;
|
|
var shorttext = text1.length > text2.length ? text2 : text1;
|
|
var i = longtext.indexOf(shorttext);
|
|
if (i !== -1) {
|
|
// Shorter text is inside the longer text (speedup).
|
|
diffs = [
|
|
[DIFF_INSERT, longtext.substring(0, i)],
|
|
[DIFF_EQUAL, shorttext],
|
|
[DIFF_INSERT, longtext.substring(i + shorttext.length)]
|
|
];
|
|
// Swap insertions for deletions if diff is reversed.
|
|
if (text1.length > text2.length) {
|
|
diffs[0][0] = diffs[2][0] = DIFF_DELETE;
|
|
}
|
|
return diffs;
|
|
}
|
|
|
|
if (shorttext.length === 1) {
|
|
// Single character string.
|
|
// After the previous speedup, the character can't be an equality.
|
|
return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
|
|
}
|
|
|
|
// Check to see if the problem can be split in two.
|
|
var hm = diff_halfMatch_(text1, text2);
|
|
if (hm) {
|
|
// A half-match was found, sort out the return data.
|
|
var text1_a = hm[0];
|
|
var text1_b = hm[1];
|
|
var text2_a = hm[2];
|
|
var text2_b = hm[3];
|
|
var mid_common = hm[4];
|
|
// Send both pairs off for separate processing.
|
|
var diffs_a = diff_main(text1_a, text2_a);
|
|
var diffs_b = diff_main(text1_b, text2_b);
|
|
// Merge the results.
|
|
return diffs_a.concat([[DIFF_EQUAL, mid_common]], diffs_b);
|
|
}
|
|
|
|
return diff_bisect_(text1, text2);
|
|
};
|
|
|
|
|
|
/**
|
|
* Find the 'middle snake' of a diff, split the problem in two
|
|
* and return the recursively constructed diff.
|
|
* See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
|
|
* @param {string} text1 Old string to be diffed.
|
|
* @param {string} text2 New string to be diffed.
|
|
* @return {Array} Array of diff tuples.
|
|
* @private
|
|
*/
|
|
function diff_bisect_(text1, text2) {
|
|
// Cache the text lengths to prevent multiple calls.
|
|
var text1_length = text1.length;
|
|
var text2_length = text2.length;
|
|
var max_d = Math.ceil((text1_length + text2_length) / 2);
|
|
var v_offset = max_d;
|
|
var v_length = 2 * max_d;
|
|
var v1 = new Array(v_length);
|
|
var v2 = new Array(v_length);
|
|
// Setting all elements to -1 is faster in Chrome & Firefox than mixing
|
|
// integers and undefined.
|
|
for (var x = 0; x < v_length; x++) {
|
|
v1[x] = -1;
|
|
v2[x] = -1;
|
|
}
|
|
v1[v_offset + 1] = 0;
|
|
v2[v_offset + 1] = 0;
|
|
var delta = text1_length - text2_length;
|
|
// If the total number of characters is odd, then the front path will collide
|
|
// with the reverse path.
|
|
var front = (delta % 2 !== 0);
|
|
// Offsets for start and end of k loop.
|
|
// Prevents mapping of space beyond the grid.
|
|
var k1start = 0;
|
|
var k1end = 0;
|
|
var k2start = 0;
|
|
var k2end = 0;
|
|
for (var d = 0; d < max_d; d++) {
|
|
// Walk the front path one step.
|
|
for (var k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
|
|
var k1_offset = v_offset + k1;
|
|
var x1;
|
|
if (k1 === -d || (k1 !== d && v1[k1_offset - 1] < v1[k1_offset + 1])) {
|
|
x1 = v1[k1_offset + 1];
|
|
} else {
|
|
x1 = v1[k1_offset - 1] + 1;
|
|
}
|
|
var y1 = x1 - k1;
|
|
while (
|
|
x1 < text1_length && y1 < text2_length &&
|
|
text1.charAt(x1) === text2.charAt(y1)
|
|
) {
|
|
x1++;
|
|
y1++;
|
|
}
|
|
v1[k1_offset] = x1;
|
|
if (x1 > text1_length) {
|
|
// Ran off the right of the graph.
|
|
k1end += 2;
|
|
} else if (y1 > text2_length) {
|
|
// Ran off the bottom of the graph.
|
|
k1start += 2;
|
|
} else if (front) {
|
|
var k2_offset = v_offset + delta - k1;
|
|
if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] !== -1) {
|
|
// Mirror x2 onto top-left coordinate system.
|
|
var x2 = text1_length - v2[k2_offset];
|
|
if (x1 >= x2) {
|
|
// Overlap detected.
|
|
return diff_bisectSplit_(text1, text2, x1, y1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Walk the reverse path one step.
|
|
for (var k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
|
|
var k2_offset = v_offset + k2;
|
|
var x2;
|
|
if (k2 === -d || (k2 !== d && v2[k2_offset - 1] < v2[k2_offset + 1])) {
|
|
x2 = v2[k2_offset + 1];
|
|
} else {
|
|
x2 = v2[k2_offset - 1] + 1;
|
|
}
|
|
var y2 = x2 - k2;
|
|
while (
|
|
x2 < text1_length && y2 < text2_length &&
|
|
text1.charAt(text1_length - x2 - 1) === text2.charAt(text2_length - y2 - 1)
|
|
) {
|
|
x2++;
|
|
y2++;
|
|
}
|
|
v2[k2_offset] = x2;
|
|
if (x2 > text1_length) {
|
|
// Ran off the left of the graph.
|
|
k2end += 2;
|
|
} else if (y2 > text2_length) {
|
|
// Ran off the top of the graph.
|
|
k2start += 2;
|
|
} else if (!front) {
|
|
var k1_offset = v_offset + delta - k2;
|
|
if (k1_offset >= 0 && k1_offset < v_length && v1[k1_offset] !== -1) {
|
|
var x1 = v1[k1_offset];
|
|
var y1 = v_offset + x1 - k1_offset;
|
|
// Mirror x2 onto top-left coordinate system.
|
|
x2 = text1_length - x2;
|
|
if (x1 >= x2) {
|
|
// Overlap detected.
|
|
return diff_bisectSplit_(text1, text2, x1, y1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Diff took too long and hit the deadline or
|
|
// number of diffs equals number of characters, no commonality at all.
|
|
return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
|
|
};
|
|
|
|
|
|
/**
|
|
* Given the location of the 'middle snake', split the diff in two parts
|
|
* and recurse.
|
|
* @param {string} text1 Old string to be diffed.
|
|
* @param {string} text2 New string to be diffed.
|
|
* @param {number} x Index of split point in text1.
|
|
* @param {number} y Index of split point in text2.
|
|
* @return {Array} Array of diff tuples.
|
|
*/
|
|
function diff_bisectSplit_(text1, text2, x, y) {
|
|
var text1a = text1.substring(0, x);
|
|
var text2a = text2.substring(0, y);
|
|
var text1b = text1.substring(x);
|
|
var text2b = text2.substring(y);
|
|
|
|
// Compute both diffs serially.
|
|
var diffs = diff_main(text1a, text2a);
|
|
var diffsb = diff_main(text1b, text2b);
|
|
|
|
return diffs.concat(diffsb);
|
|
};
|
|
|
|
|
|
/**
|
|
* Determine the common prefix of two strings.
|
|
* @param {string} text1 First string.
|
|
* @param {string} text2 Second string.
|
|
* @return {number} The number of characters common to the start of each
|
|
* string.
|
|
*/
|
|
function diff_commonPrefix(text1, text2) {
|
|
// Quick check for common null cases.
|
|
if (!text1 || !text2 || text1.charAt(0) !== text2.charAt(0)) {
|
|
return 0;
|
|
}
|
|
// Binary search.
|
|
// Performance analysis: http://neil.fraser.name/news/2007/10/09/
|
|
var pointermin = 0;
|
|
var pointermax = Math.min(text1.length, text2.length);
|
|
var pointermid = pointermax;
|
|
var pointerstart = 0;
|
|
while (pointermin < pointermid) {
|
|
if (
|
|
text1.substring(pointerstart, pointermid) ==
|
|
text2.substring(pointerstart, pointermid)
|
|
) {
|
|
pointermin = pointermid;
|
|
pointerstart = pointermin;
|
|
} else {
|
|
pointermax = pointermid;
|
|
}
|
|
pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
|
|
}
|
|
|
|
if (is_surrogate_pair_start(text1.charCodeAt(pointermid - 1))) {
|
|
pointermid--;
|
|
}
|
|
|
|
return pointermid;
|
|
};
|
|
|
|
|
|
/**
|
|
* Determine the common suffix of two strings.
|
|
* @param {string} text1 First string.
|
|
* @param {string} text2 Second string.
|
|
* @return {number} The number of characters common to the end of each string.
|
|
*/
|
|
function diff_commonSuffix(text1, text2) {
|
|
// Quick check for common null cases.
|
|
if (!text1 || !text2 || text1.slice(-1) !== text2.slice(-1)) {
|
|
return 0;
|
|
}
|
|
// Binary search.
|
|
// Performance analysis: http://neil.fraser.name/news/2007/10/09/
|
|
var pointermin = 0;
|
|
var pointermax = Math.min(text1.length, text2.length);
|
|
var pointermid = pointermax;
|
|
var pointerend = 0;
|
|
while (pointermin < pointermid) {
|
|
if (
|
|
text1.substring(text1.length - pointermid, text1.length - pointerend) ==
|
|
text2.substring(text2.length - pointermid, text2.length - pointerend)
|
|
) {
|
|
pointermin = pointermid;
|
|
pointerend = pointermin;
|
|
} else {
|
|
pointermax = pointermid;
|
|
}
|
|
pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
|
|
}
|
|
|
|
if (is_surrogate_pair_end(text1.charCodeAt(text1.length - pointermid))) {
|
|
pointermid--;
|
|
}
|
|
|
|
return pointermid;
|
|
};
|
|
|
|
|
|
/**
|
|
* Do the two texts share a substring which is at least half the length of the
|
|
* longer text?
|
|
* This speedup can produce non-minimal diffs.
|
|
* @param {string} text1 First string.
|
|
* @param {string} text2 Second string.
|
|
* @return {Array.<string>} Five element Array, containing the prefix of
|
|
* text1, the suffix of text1, the prefix of text2, the suffix of
|
|
* text2 and the common middle. Or null if there was no match.
|
|
*/
|
|
function diff_halfMatch_(text1, text2) {
|
|
var longtext = text1.length > text2.length ? text1 : text2;
|
|
var shorttext = text1.length > text2.length ? text2 : text1;
|
|
if (longtext.length < 4 || shorttext.length * 2 < longtext.length) {
|
|
return null; // Pointless.
|
|
}
|
|
|
|
/**
|
|
* Does a substring of shorttext exist within longtext such that the substring
|
|
* is at least half the length of longtext?
|
|
* Closure, but does not reference any external variables.
|
|
* @param {string} longtext Longer string.
|
|
* @param {string} shorttext Shorter string.
|
|
* @param {number} i Start index of quarter length substring within longtext.
|
|
* @return {Array.<string>} Five element Array, containing the prefix of
|
|
* longtext, the suffix of longtext, the prefix of shorttext, the suffix
|
|
* of shorttext and the common middle. Or null if there was no match.
|
|
* @private
|
|
*/
|
|
function diff_halfMatchI_(longtext, shorttext, i) {
|
|
// Start with a 1/4 length substring at position i as a seed.
|
|
var seed = longtext.substring(i, i + Math.floor(longtext.length / 4));
|
|
var j = -1;
|
|
var best_common = '';
|
|
var best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b;
|
|
while ((j = shorttext.indexOf(seed, j + 1)) !== -1) {
|
|
var prefixLength = diff_commonPrefix(
|
|
longtext.substring(i), shorttext.substring(j));
|
|
var suffixLength = diff_commonSuffix(
|
|
longtext.substring(0, i), shorttext.substring(0, j));
|
|
if (best_common.length < suffixLength + prefixLength) {
|
|
best_common = shorttext.substring(
|
|
j - suffixLength, j) + shorttext.substring(j, j + prefixLength);
|
|
best_longtext_a = longtext.substring(0, i - suffixLength);
|
|
best_longtext_b = longtext.substring(i + prefixLength);
|
|
best_shorttext_a = shorttext.substring(0, j - suffixLength);
|
|
best_shorttext_b = shorttext.substring(j + prefixLength);
|
|
}
|
|
}
|
|
if (best_common.length * 2 >= longtext.length) {
|
|
return [
|
|
best_longtext_a, best_longtext_b,
|
|
best_shorttext_a, best_shorttext_b, best_common
|
|
];
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// First check if the second quarter is the seed for a half-match.
|
|
var hm1 = diff_halfMatchI_(longtext, shorttext, Math.ceil(longtext.length / 4));
|
|
// Check again based on the third quarter.
|
|
var hm2 = diff_halfMatchI_(longtext, shorttext, Math.ceil(longtext.length / 2));
|
|
var hm;
|
|
if (!hm1 && !hm2) {
|
|
return null;
|
|
} else if (!hm2) {
|
|
hm = hm1;
|
|
} else if (!hm1) {
|
|
hm = hm2;
|
|
} else {
|
|
// Both matched. Select the longest.
|
|
hm = hm1[4].length > hm2[4].length ? hm1 : hm2;
|
|
}
|
|
|
|
// A half-match was found, sort out the return data.
|
|
var text1_a, text1_b, text2_a, text2_b;
|
|
if (text1.length > text2.length) {
|
|
text1_a = hm[0];
|
|
text1_b = hm[1];
|
|
text2_a = hm[2];
|
|
text2_b = hm[3];
|
|
} else {
|
|
text2_a = hm[0];
|
|
text2_b = hm[1];
|
|
text1_a = hm[2];
|
|
text1_b = hm[3];
|
|
}
|
|
var mid_common = hm[4];
|
|
return [text1_a, text1_b, text2_a, text2_b, mid_common];
|
|
};
|
|
|
|
|
|
/**
|
|
* Reorder and merge like edit sections. Merge equalities.
|
|
* Any edit section can move as long as it doesn't cross an equality.
|
|
* @param {Array} diffs Array of diff tuples.
|
|
* @param {boolean} fix_unicode Whether to normalize to a unicode-correct diff
|
|
*/
|
|
function diff_cleanupMerge(diffs, fix_unicode) {
|
|
diffs.push([DIFF_EQUAL, '']); // Add a dummy entry at the end.
|
|
var pointer = 0;
|
|
var count_delete = 0;
|
|
var count_insert = 0;
|
|
var text_delete = '';
|
|
var text_insert = '';
|
|
var commonlength;
|
|
while (pointer < diffs.length) {
|
|
if (pointer < diffs.length - 1 && !diffs[pointer][1]) {
|
|
diffs.splice(pointer, 1);
|
|
continue;
|
|
}
|
|
switch (diffs[pointer][0]) {
|
|
case DIFF_INSERT:
|
|
|
|
count_insert++;
|
|
text_insert += diffs[pointer][1];
|
|
pointer++;
|
|
break;
|
|
case DIFF_DELETE:
|
|
count_delete++;
|
|
text_delete += diffs[pointer][1];
|
|
pointer++;
|
|
break;
|
|
case DIFF_EQUAL:
|
|
var previous_equality = pointer - count_insert - count_delete - 1;
|
|
if (fix_unicode) {
|
|
// prevent splitting of unicode surrogate pairs. when fix_unicode is true,
|
|
// we assume that the old and new text in the diff are complete and correct
|
|
// unicode-encoded JS strings, but the tuple boundaries may fall between
|
|
// surrogate pairs. we fix this by shaving off stray surrogates from the end
|
|
// of the previous equality and the beginning of this equality. this may create
|
|
// empty equalities or a common prefix or suffix. for example, if AB and AC are
|
|
// emojis, `[[0, 'A'], [-1, 'BA'], [0, 'C']]` would turn into deleting 'ABAC' and
|
|
// inserting 'AC', and then the common suffix 'AC' will be eliminated. in this
|
|
// particular case, both equalities go away, we absorb any previous inequalities,
|
|
// and we keep scanning for the next equality before rewriting the tuples.
|
|
if (previous_equality >= 0 && ends_with_pair_start(diffs[previous_equality][1])) {
|
|
var stray = diffs[previous_equality][1].slice(-1);
|
|
diffs[previous_equality][1] = diffs[previous_equality][1].slice(0, -1);
|
|
text_delete = stray + text_delete;
|
|
text_insert = stray + text_insert;
|
|
if (!diffs[previous_equality][1]) {
|
|
// emptied out previous equality, so delete it and include previous delete/insert
|
|
diffs.splice(previous_equality, 1);
|
|
pointer--;
|
|
var k = previous_equality - 1;
|
|
if (diffs[k] && diffs[k][0] === DIFF_INSERT) {
|
|
count_insert++;
|
|
text_insert = diffs[k][1] + text_insert;
|
|
k--;
|
|
}
|
|
if (diffs[k] && diffs[k][0] === DIFF_DELETE) {
|
|
count_delete++;
|
|
text_delete = diffs[k][1] + text_delete;
|
|
k--;
|
|
}
|
|
previous_equality = k;
|
|
}
|
|
}
|
|
if (starts_with_pair_end(diffs[pointer][1])) {
|
|
var stray = diffs[pointer][1].charAt(0);
|
|
diffs[pointer][1] = diffs[pointer][1].slice(1);
|
|
text_delete += stray;
|
|
text_insert += stray;
|
|
}
|
|
}
|
|
if (pointer < diffs.length - 1 && !diffs[pointer][1]) {
|
|
// for empty equality not at end, wait for next equality
|
|
diffs.splice(pointer, 1);
|
|
break;
|
|
}
|
|
if (text_delete.length > 0 || text_insert.length > 0) {
|
|
// note that diff_commonPrefix and diff_commonSuffix are unicode-aware
|
|
if (text_delete.length > 0 && text_insert.length > 0) {
|
|
// Factor out any common prefixes.
|
|
commonlength = diff_commonPrefix(text_insert, text_delete);
|
|
if (commonlength !== 0) {
|
|
if (previous_equality >= 0) {
|
|
diffs[previous_equality][1] += text_insert.substring(0, commonlength);
|
|
} else {
|
|
diffs.splice(0, 0, [DIFF_EQUAL, text_insert.substring(0, commonlength)]);
|
|
pointer++;
|
|
}
|
|
text_insert = text_insert.substring(commonlength);
|
|
text_delete = text_delete.substring(commonlength);
|
|
}
|
|
// Factor out any common suffixes.
|
|
commonlength = diff_commonSuffix(text_insert, text_delete);
|
|
if (commonlength !== 0) {
|
|
diffs[pointer][1] =
|
|
text_insert.substring(text_insert.length - commonlength) + diffs[pointer][1];
|
|
text_insert = text_insert.substring(0, text_insert.length - commonlength);
|
|
text_delete = text_delete.substring(0, text_delete.length - commonlength);
|
|
}
|
|
}
|
|
// Delete the offending records and add the merged ones.
|
|
var n = count_insert + count_delete;
|
|
if (text_delete.length === 0 && text_insert.length === 0) {
|
|
diffs.splice(pointer - n, n);
|
|
pointer = pointer - n;
|
|
} else if (text_delete.length === 0) {
|
|
diffs.splice(pointer - n, n, [DIFF_INSERT, text_insert]);
|
|
pointer = pointer - n + 1;
|
|
} else if (text_insert.length === 0) {
|
|
diffs.splice(pointer - n, n, [DIFF_DELETE, text_delete]);
|
|
pointer = pointer - n + 1;
|
|
} else {
|
|
diffs.splice(pointer - n, n, [DIFF_DELETE, text_delete], [DIFF_INSERT, text_insert]);
|
|
pointer = pointer - n + 2;
|
|
}
|
|
}
|
|
if (pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL) {
|
|
// Merge this equality with the previous one.
|
|
diffs[pointer - 1][1] += diffs[pointer][1];
|
|
diffs.splice(pointer, 1);
|
|
} else {
|
|
pointer++;
|
|
}
|
|
count_insert = 0;
|
|
count_delete = 0;
|
|
text_delete = '';
|
|
text_insert = '';
|
|
break;
|
|
}
|
|
}
|
|
if (diffs[diffs.length - 1][1] === '') {
|
|
diffs.pop(); // Remove the dummy entry at the end.
|
|
}
|
|
|
|
// Second pass: look for single edits surrounded on both sides by equalities
|
|
// which can be shifted sideways to eliminate an equality.
|
|
// e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
|
|
var changes = false;
|
|
pointer = 1;
|
|
// Intentionally ignore the first and last element (don't need checking).
|
|
while (pointer < diffs.length - 1) {
|
|
if (diffs[pointer - 1][0] === DIFF_EQUAL &&
|
|
diffs[pointer + 1][0] === DIFF_EQUAL) {
|
|
// This is a single edit surrounded by equalities.
|
|
if (diffs[pointer][1].substring(diffs[pointer][1].length -
|
|
diffs[pointer - 1][1].length) === diffs[pointer - 1][1]) {
|
|
// Shift the edit over the previous equality.
|
|
diffs[pointer][1] = diffs[pointer - 1][1] +
|
|
diffs[pointer][1].substring(0, diffs[pointer][1].length -
|
|
diffs[pointer - 1][1].length);
|
|
diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];
|
|
diffs.splice(pointer - 1, 1);
|
|
changes = true;
|
|
} else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) ==
|
|
diffs[pointer + 1][1]) {
|
|
// Shift the edit over the next equality.
|
|
diffs[pointer - 1][1] += diffs[pointer + 1][1];
|
|
diffs[pointer][1] =
|
|
diffs[pointer][1].substring(diffs[pointer + 1][1].length) +
|
|
diffs[pointer + 1][1];
|
|
diffs.splice(pointer + 1, 1);
|
|
changes = true;
|
|
}
|
|
}
|
|
pointer++;
|
|
}
|
|
// If shifts were made, the diff needs reordering and another shift sweep.
|
|
if (changes) {
|
|
diff_cleanupMerge(diffs, fix_unicode);
|
|
}
|
|
};
|
|
|
|
function is_surrogate_pair_start(charCode) {
|
|
return charCode >= 0xD800 && charCode <= 0xDBFF;
|
|
}
|
|
|
|
function is_surrogate_pair_end(charCode) {
|
|
return charCode >= 0xDC00 && charCode <= 0xDFFF;
|
|
}
|
|
|
|
function starts_with_pair_end(str) {
|
|
return is_surrogate_pair_end(str.charCodeAt(0));
|
|
}
|
|
|
|
function ends_with_pair_start(str) {
|
|
return is_surrogate_pair_start(str.charCodeAt(str.length - 1));
|
|
}
|
|
|
|
function remove_empty_tuples(tuples) {
|
|
var ret = [];
|
|
for (var i = 0; i < tuples.length; i++) {
|
|
if (tuples[i][1].length > 0) {
|
|
ret.push(tuples[i]);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
function make_edit_splice(before, oldMiddle, newMiddle, after) {
|
|
if (ends_with_pair_start(before) || starts_with_pair_end(after)) {
|
|
return null;
|
|
}
|
|
return remove_empty_tuples([
|
|
[DIFF_EQUAL, before],
|
|
[DIFF_DELETE, oldMiddle],
|
|
[DIFF_INSERT, newMiddle],
|
|
[DIFF_EQUAL, after]
|
|
]);
|
|
}
|
|
|
|
function find_cursor_edit_diff(oldText, newText, cursor_pos) {
|
|
// note: this runs after equality check has ruled out exact equality
|
|
var oldRange = typeof cursor_pos === 'number' ?
|
|
{ index: cursor_pos, length: 0 } : cursor_pos.oldRange;
|
|
var newRange = typeof cursor_pos === 'number' ?
|
|
null : cursor_pos.newRange;
|
|
// take into account the old and new selection to generate the best diff
|
|
// possible for a text edit. for example, a text change from "xxx" to "xx"
|
|
// could be a delete or forwards-delete of any one of the x's, or the
|
|
// result of selecting two of the x's and typing "x".
|
|
var oldLength = oldText.length;
|
|
var newLength = newText.length;
|
|
if (oldRange.length === 0 && (newRange === null || newRange.length === 0)) {
|
|
// see if we have an insert or delete before or after cursor
|
|
var oldCursor = oldRange.index;
|
|
var oldBefore = oldText.slice(0, oldCursor);
|
|
var oldAfter = oldText.slice(oldCursor);
|
|
var maybeNewCursor = newRange ? newRange.index : null;
|
|
editBefore: {
|
|
// is this an insert or delete right before oldCursor?
|
|
var newCursor = oldCursor + newLength - oldLength;
|
|
if (maybeNewCursor !== null && maybeNewCursor !== newCursor) {
|
|
break editBefore;
|
|
}
|
|
if (newCursor < 0 || newCursor > newLength) {
|
|
break editBefore;
|
|
}
|
|
var newBefore = newText.slice(0, newCursor);
|
|
var newAfter = newText.slice(newCursor);
|
|
if (newAfter !== oldAfter) {
|
|
break editBefore;
|
|
}
|
|
var prefixLength = Math.min(oldCursor, newCursor);
|
|
var oldPrefix = oldBefore.slice(0, prefixLength);
|
|
var newPrefix = newBefore.slice(0, prefixLength);
|
|
if (oldPrefix !== newPrefix) {
|
|
break editBefore;
|
|
}
|
|
var oldMiddle = oldBefore.slice(prefixLength);
|
|
var newMiddle = newBefore.slice(prefixLength);
|
|
return make_edit_splice(oldPrefix, oldMiddle, newMiddle, oldAfter);
|
|
}
|
|
editAfter: {
|
|
// is this an insert or delete right after oldCursor?
|
|
if (maybeNewCursor !== null && maybeNewCursor !== oldCursor) {
|
|
break editAfter;
|
|
}
|
|
var cursor = oldCursor;
|
|
var newBefore = newText.slice(0, cursor);
|
|
var newAfter = newText.slice(cursor);
|
|
if (newBefore !== oldBefore) {
|
|
break editAfter;
|
|
}
|
|
var suffixLength = Math.min(oldLength - cursor, newLength - cursor);
|
|
var oldSuffix = oldAfter.slice(oldAfter.length - suffixLength);
|
|
var newSuffix = newAfter.slice(newAfter.length - suffixLength);
|
|
if (oldSuffix !== newSuffix) {
|
|
break editAfter;
|
|
}
|
|
var oldMiddle = oldAfter.slice(0, oldAfter.length - suffixLength);
|
|
var newMiddle = newAfter.slice(0, newAfter.length - suffixLength);
|
|
return make_edit_splice(oldBefore, oldMiddle, newMiddle, oldSuffix);
|
|
}
|
|
}
|
|
if (oldRange.length > 0 && newRange && newRange.length === 0) {
|
|
replaceRange: {
|
|
// see if diff could be a splice of the old selection range
|
|
var oldPrefix = oldText.slice(0, oldRange.index);
|
|
var oldSuffix = oldText.slice(oldRange.index + oldRange.length);
|
|
var prefixLength = oldPrefix.length;
|
|
var suffixLength = oldSuffix.length;
|
|
if (newLength < prefixLength + suffixLength) {
|
|
break replaceRange;
|
|
}
|
|
var newPrefix = newText.slice(0, prefixLength);
|
|
var newSuffix = newText.slice(newLength - suffixLength);
|
|
if (oldPrefix !== newPrefix || oldSuffix !== newSuffix) {
|
|
break replaceRange;
|
|
}
|
|
var oldMiddle = oldText.slice(prefixLength, oldLength - suffixLength);
|
|
var newMiddle = newText.slice(prefixLength, newLength - suffixLength);
|
|
return make_edit_splice(oldPrefix, oldMiddle, newMiddle, oldSuffix);
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function diff(text1, text2, cursor_pos) {
|
|
// only pass fix_unicode=true at the top level, not when diff_main is
|
|
// recursively invoked
|
|
return diff_main(text1, text2, cursor_pos, true);
|
|
}
|
|
|
|
diff.INSERT = DIFF_INSERT;
|
|
diff.DELETE = DIFF_DELETE;
|
|
diff.EQUAL = DIFF_EQUAL;
|
|
|
|
module.exports = diff;
|
|
|
|
|
|
/***/ }),
|
|
/* 210 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
// nvim use utf8
|
|
function byteLength(str) {
|
|
return Buffer.byteLength(str);
|
|
}
|
|
exports.byteLength = byteLength;
|
|
function upperFirst(str) {
|
|
return str ? str[0].toUpperCase() + str.slice(1) : '';
|
|
}
|
|
exports.upperFirst = upperFirst;
|
|
function byteIndex(content, index) {
|
|
let s = content.slice(0, index);
|
|
return Buffer.byteLength(s);
|
|
}
|
|
exports.byteIndex = byteIndex;
|
|
function indexOf(str, ch, count = 1) {
|
|
let curr = 0;
|
|
for (let i = 0; i < str.length; i++) {
|
|
if (str[i] == ch) {
|
|
curr = curr + 1;
|
|
if (curr == count) {
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
exports.indexOf = indexOf;
|
|
function characterIndex(content, byteIndex) {
|
|
let buf = Buffer.from(content, 'utf8');
|
|
return buf.slice(0, byteIndex).toString('utf8').length;
|
|
}
|
|
exports.characterIndex = characterIndex;
|
|
function byteSlice(content, start, end) {
|
|
let buf = Buffer.from(content, 'utf8');
|
|
return buf.slice(start, end).toString('utf8');
|
|
}
|
|
exports.byteSlice = byteSlice;
|
|
function isWord(character) {
|
|
let code = character.charCodeAt(0);
|
|
if (code > 128)
|
|
return false;
|
|
if (code == 95)
|
|
return true;
|
|
if (code >= 48 && code <= 57)
|
|
return true;
|
|
if (code >= 65 && code <= 90)
|
|
return true;
|
|
if (code >= 97 && code <= 122)
|
|
return true;
|
|
return false;
|
|
}
|
|
exports.isWord = isWord;
|
|
function isTriggerCharacter(character) {
|
|
if (!character)
|
|
return false;
|
|
let code = character.charCodeAt(0);
|
|
if (code > 128)
|
|
return false;
|
|
if (code >= 65 && code <= 90)
|
|
return false;
|
|
if (code >= 97 && code <= 122)
|
|
return false;
|
|
return true;
|
|
}
|
|
exports.isTriggerCharacter = isTriggerCharacter;
|
|
function resolveVariables(str, variables) {
|
|
const regexp = /\$\{(.*?)\}/g;
|
|
return str.replace(regexp, (match, name) => {
|
|
const newValue = variables[name];
|
|
if (typeof newValue === 'string') {
|
|
return newValue;
|
|
}
|
|
return match;
|
|
});
|
|
}
|
|
exports.resolveVariables = resolveVariables;
|
|
function isAsciiLetter(code) {
|
|
if (code >= 65 && code <= 90)
|
|
return true;
|
|
if (code >= 97 && code <= 122)
|
|
return true;
|
|
return false;
|
|
}
|
|
exports.isAsciiLetter = isAsciiLetter;
|
|
function doEqualsIgnoreCase(a, b, stopAt = a.length) {
|
|
if (typeof a !== 'string' || typeof b !== 'string') {
|
|
return false;
|
|
}
|
|
for (let i = 0; i < stopAt; i++) {
|
|
const codeA = a.charCodeAt(i);
|
|
const codeB = b.charCodeAt(i);
|
|
if (codeA === codeB) {
|
|
continue;
|
|
}
|
|
// a-z A-Z
|
|
if (isAsciiLetter(codeA) && isAsciiLetter(codeB)) {
|
|
const diff = Math.abs(codeA - codeB);
|
|
if (diff !== 0 && diff !== 32) {
|
|
return false;
|
|
}
|
|
}
|
|
// Any other charcode
|
|
else {
|
|
if (String.fromCharCode(codeA).toLowerCase() !== String.fromCharCode(codeB).toLowerCase()) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
function equalsIgnoreCase(a, b) {
|
|
const len1 = a ? a.length : 0;
|
|
const len2 = b ? b.length : 0;
|
|
if (len1 !== len2) {
|
|
return false;
|
|
}
|
|
return doEqualsIgnoreCase(a, b);
|
|
}
|
|
exports.equalsIgnoreCase = equalsIgnoreCase;
|
|
//# sourceMappingURL=string.js.map
|
|
|
|
/***/ }),
|
|
/* 211 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const logger = __webpack_require__(186)('model-chars');
|
|
class Range {
|
|
constructor(start, end) {
|
|
this.start = start;
|
|
this.end = end ? end : start;
|
|
}
|
|
static fromKeywordOption(keywordOption) {
|
|
let parts = keywordOption.split(',');
|
|
let ranges = [];
|
|
for (let part of parts) {
|
|
if (part == '@') {
|
|
// isalpha() of c
|
|
ranges.push(new Range(65, 90));
|
|
ranges.push(new Range(97, 122));
|
|
}
|
|
else if (part == '@-@') {
|
|
ranges.push(new Range(64));
|
|
}
|
|
else if (/^([A-Za-z])-([A-Za-z])$/.test(part)) {
|
|
let ms = part.match(/^([A-Za-z])-([A-Za-z])$/);
|
|
ranges.push(new Range(ms[1].charCodeAt(0), ms[2].charCodeAt(0)));
|
|
}
|
|
else if (/^\d+-\d+$/.test(part)) {
|
|
let ms = part.match(/^(\d+)-(\d+)$/);
|
|
ranges.push(new Range(Number(ms[1]), Number(ms[2])));
|
|
}
|
|
else if (/^\d+$/.test(part)) {
|
|
ranges.push(new Range(Number(part)));
|
|
}
|
|
else {
|
|
let c = part.charCodeAt(0);
|
|
if (!ranges.some(o => o.contains(c))) {
|
|
ranges.push(new Range(c));
|
|
}
|
|
}
|
|
}
|
|
return ranges;
|
|
}
|
|
contains(c) {
|
|
return c >= this.start && c <= this.end;
|
|
}
|
|
}
|
|
exports.Range = Range;
|
|
class Chars {
|
|
constructor(keywordOption) {
|
|
this.ranges = [];
|
|
if (keywordOption)
|
|
this.ranges = Range.fromKeywordOption(keywordOption);
|
|
}
|
|
addKeyword(ch) {
|
|
let c = ch.charCodeAt(0);
|
|
let { ranges } = this;
|
|
if (!ranges.some(o => o.contains(c))) {
|
|
ranges.push(new Range(c));
|
|
}
|
|
}
|
|
clone() {
|
|
let chars = new Chars();
|
|
chars.ranges = this.ranges.slice();
|
|
return chars;
|
|
}
|
|
setKeywordOption(keywordOption) {
|
|
this.ranges = Range.fromKeywordOption(keywordOption);
|
|
}
|
|
matchKeywords(content, min = 3) {
|
|
let length = content.length;
|
|
if (length == 0)
|
|
return [];
|
|
let res = new Set();
|
|
let str = '';
|
|
let len = 0;
|
|
for (let i = 0; i < length; i++) {
|
|
let ch = content[i];
|
|
let code = ch.codePointAt(0);
|
|
if (len == 0 && code == 45)
|
|
continue;
|
|
let isKeyword = this.isKeywordCode(code);
|
|
if (isKeyword) {
|
|
if (len == 48)
|
|
continue;
|
|
str = str + ch;
|
|
len = len + 1;
|
|
}
|
|
else {
|
|
if (len >= min && len < 48)
|
|
res.add(str);
|
|
str = '';
|
|
len = 0;
|
|
}
|
|
}
|
|
if (len != 0)
|
|
res.add(str);
|
|
return Array.from(res);
|
|
}
|
|
isKeywordCode(code) {
|
|
if (code > 255)
|
|
return true;
|
|
if (code < 33)
|
|
return false;
|
|
return this.ranges.some(r => r.contains(code));
|
|
}
|
|
isKeywordChar(ch) {
|
|
let { ranges } = this;
|
|
let c = ch.charCodeAt(0);
|
|
if (c > 255)
|
|
return true;
|
|
if (c < 33)
|
|
return false;
|
|
return ranges.some(r => r.contains(c));
|
|
}
|
|
isKeyword(word) {
|
|
let { ranges } = this;
|
|
for (let i = 0, l = word.length; i < l; i++) {
|
|
let ch = word.charCodeAt(i);
|
|
// for speed
|
|
if (ch > 255)
|
|
return false;
|
|
if (ranges.some(r => r.contains(ch)))
|
|
continue;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
exports.Chars = Chars;
|
|
//# sourceMappingURL=chars.js.map
|
|
|
|
/***/ }),
|
|
/* 212 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
function intersect(array, other) {
|
|
for (let item of other) {
|
|
if (array.indexOf(item) !== -1) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
exports.intersect = intersect;
|
|
function tail(array, n = 0) {
|
|
return array[array.length - (1 + n)];
|
|
}
|
|
exports.tail = tail;
|
|
function group(array, size) {
|
|
let len = array.length;
|
|
let res = [];
|
|
for (let i = 0; i < Math.ceil(len / size); i++) {
|
|
res.push(array.slice(i * size, (i + 1) * size));
|
|
}
|
|
return res;
|
|
}
|
|
exports.group = group;
|
|
/**
|
|
* Removes duplicates from the given array. The optional keyFn allows to specify
|
|
* how elements are checked for equalness by returning a unique string for each.
|
|
*/
|
|
function distinct(array, keyFn) {
|
|
if (!keyFn) {
|
|
return array.filter((element, position) => {
|
|
return array.indexOf(element) === position;
|
|
});
|
|
}
|
|
const seen = Object.create(null);
|
|
return array.filter(elem => {
|
|
const key = keyFn(elem);
|
|
if (seen[key]) {
|
|
return false;
|
|
}
|
|
seen[key] = true;
|
|
return true;
|
|
});
|
|
}
|
|
exports.distinct = distinct;
|
|
function lastIndex(array, fn) {
|
|
let i = array.length - 1;
|
|
while (i >= 0) {
|
|
if (fn(array[i])) {
|
|
break;
|
|
}
|
|
i--;
|
|
}
|
|
return i;
|
|
}
|
|
exports.lastIndex = lastIndex;
|
|
exports.flatMap = (xs, f) => xs.reduce((x, y) => [...x, ...f(y)], []);
|
|
//# sourceMappingURL=array.js.map
|
|
|
|
/***/ }),
|
|
/* 213 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
function rangeInRange(r, range) {
|
|
return positionInRange(r.start, range) === 0 && positionInRange(r.end, range) === 0;
|
|
}
|
|
exports.rangeInRange = rangeInRange;
|
|
/**
|
|
* Check if two ranges have overlap character.
|
|
*/
|
|
function rangeOverlap(r, range) {
|
|
let { start, end } = r;
|
|
if (comparePosition(end, range.start) <= 0) {
|
|
return false;
|
|
}
|
|
if (comparePosition(start, range.end) >= 0) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
exports.rangeOverlap = rangeOverlap;
|
|
/**
|
|
* Check if two ranges have overlap or nested
|
|
*/
|
|
function rangeIntersect(r, range) {
|
|
if (positionInRange(r.start, range) == 0) {
|
|
return true;
|
|
}
|
|
if (positionInRange(r.end, range) == 0) {
|
|
return true;
|
|
}
|
|
if (rangeInRange(range, r)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
exports.rangeIntersect = rangeIntersect;
|
|
function lineInRange(line, range) {
|
|
let { start, end } = range;
|
|
return line >= start.line && line <= end.line;
|
|
}
|
|
exports.lineInRange = lineInRange;
|
|
function emptyRange(range) {
|
|
let { start, end } = range;
|
|
return start.line == end.line && start.character == end.character;
|
|
}
|
|
exports.emptyRange = emptyRange;
|
|
function positionInRange(position, range) {
|
|
let { start, end } = range;
|
|
if (comparePosition(position, start) < 0)
|
|
return -1;
|
|
if (comparePosition(position, end) > 0)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
exports.positionInRange = positionInRange;
|
|
function comparePosition(position, other) {
|
|
if (position.line > other.line)
|
|
return 1;
|
|
if (other.line == position.line && position.character > other.character)
|
|
return 1;
|
|
if (other.line == position.line && position.character == other.character)
|
|
return 0;
|
|
return -1;
|
|
}
|
|
exports.comparePosition = comparePosition;
|
|
function isSingleLine(range) {
|
|
return range.start.line == range.end.line;
|
|
}
|
|
exports.isSingleLine = isSingleLine;
|
|
function getChangedPosition(start, edit) {
|
|
let { range, newText } = edit;
|
|
if (comparePosition(range.end, start) <= 0) {
|
|
let lines = newText.split('\n');
|
|
let lineCount = lines.length - (range.end.line - range.start.line) - 1;
|
|
let characterCount = 0;
|
|
if (range.end.line == start.line) {
|
|
let single = isSingleLine(range) && lineCount == 0;
|
|
let removed = single ? range.end.character - range.start.character : range.end.character;
|
|
let added = single ? newText.length : lines[lines.length - 1].length;
|
|
characterCount = added - removed;
|
|
}
|
|
return { line: lineCount, character: characterCount };
|
|
}
|
|
return { line: 0, character: 0 };
|
|
}
|
|
exports.getChangedPosition = getChangedPosition;
|
|
function adjustPosition(pos, edit) {
|
|
let { range, newText } = edit;
|
|
if (comparePosition(range.start, pos) > 1)
|
|
return pos;
|
|
let { start, end } = range;
|
|
let newLines = newText.split('\n');
|
|
let delta = (end.line - start.line) - newLines.length + 1;
|
|
let lastLine = newLines[newLines.length - 1];
|
|
let line = pos.line - delta;
|
|
if (pos.line != end.line)
|
|
return { line, character: pos.character };
|
|
let pre = newLines.length == 1 && start.line != end.line ? start.character : 0;
|
|
let removed = start.line == end.line && newLines.length == 1 ? end.character - start.character : end.character;
|
|
let character = pre + pos.character + lastLine.length - removed;
|
|
return {
|
|
line,
|
|
character
|
|
};
|
|
}
|
|
exports.adjustPosition = adjustPosition;
|
|
function positionToOffset(lines, line, character) {
|
|
let offset = 0;
|
|
for (let i = 0; i <= line; i++) {
|
|
if (i == line) {
|
|
offset += character;
|
|
}
|
|
else {
|
|
offset += lines[i].length + 1;
|
|
}
|
|
}
|
|
return offset;
|
|
}
|
|
exports.positionToOffset = positionToOffset;
|
|
// edit a range to newText
|
|
function editRange(range, text, edit) {
|
|
// outof range
|
|
if (!rangeInRange(edit.range, range))
|
|
return text;
|
|
let { start, end } = edit.range;
|
|
let lines = text.split('\n');
|
|
let character = start.line == range.start.line ? start.character - range.start.character : start.character;
|
|
let startOffset = positionToOffset(lines, start.line - range.start.line, character);
|
|
character = end.line == range.start.line ? end.character - range.start.character : end.character;
|
|
let endOffset = positionToOffset(lines, end.line - range.start.line, character);
|
|
return `${text.slice(0, startOffset)}${edit.newText}${text.slice(endOffset, text.length)}`;
|
|
}
|
|
exports.editRange = editRange;
|
|
function getChangedFromEdits(start, edits) {
|
|
let changed = { line: 0, character: 0 };
|
|
for (let edit of edits) {
|
|
let d = getChangedPosition(start, edit);
|
|
changed = { line: changed.line + d.line, character: changed.character + d.character };
|
|
}
|
|
return changed.line == 0 && changed.character == 0 ? null : changed;
|
|
}
|
|
exports.getChangedFromEdits = getChangedFromEdits;
|
|
//# sourceMappingURL=position.js.map
|
|
|
|
/***/ }),
|
|
/* 214 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const path = __webpack_require__(57);
|
|
const util_1 = __webpack_require__(174);
|
|
const logger = __webpack_require__(186)('filesystem-watcher');
|
|
class FileSystemWatcher {
|
|
constructor(clientPromise, globPattern, ignoreCreateEvents, ignoreChangeEvents, ignoreDeleteEvents) {
|
|
this.globPattern = globPattern;
|
|
this.ignoreCreateEvents = ignoreCreateEvents;
|
|
this.ignoreChangeEvents = ignoreChangeEvents;
|
|
this.ignoreDeleteEvents = ignoreDeleteEvents;
|
|
this._onDidCreate = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidChange = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidDelete = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidRename = new vscode_languageserver_protocol_1.Emitter();
|
|
this.onDidCreate = this._onDidCreate.event;
|
|
this.onDidChange = this._onDidChange.event;
|
|
this.onDidDelete = this._onDidDelete.event;
|
|
this.onDidRename = this._onDidRename.event;
|
|
this.disposables = [];
|
|
if (!clientPromise)
|
|
return;
|
|
clientPromise.then(client => {
|
|
if (client)
|
|
return this.listen(client);
|
|
}).catch(error => {
|
|
logger.error('watchman initialize failed');
|
|
logger.error(error.stack);
|
|
});
|
|
}
|
|
async listen(client) {
|
|
let { globPattern, ignoreCreateEvents, ignoreChangeEvents, ignoreDeleteEvents } = this;
|
|
let disposable = await client.subscribe(globPattern, (change) => {
|
|
let { root, files } = change;
|
|
files = files.filter(f => f.type == 'f');
|
|
for (let file of files) {
|
|
let uri = vscode_uri_1.URI.file(path.join(root, file.name));
|
|
if (!file.exists) {
|
|
if (!ignoreDeleteEvents)
|
|
this._onDidDelete.fire(uri);
|
|
}
|
|
else {
|
|
if (file.size != 0) {
|
|
if (!ignoreChangeEvents)
|
|
this._onDidChange.fire(uri);
|
|
}
|
|
else {
|
|
if (!ignoreCreateEvents)
|
|
this._onDidCreate.fire(uri);
|
|
}
|
|
}
|
|
}
|
|
if (files.length == 2 && !files[0].exists && files[1].exists) {
|
|
let oldFile = files[0];
|
|
let newFile = files[1];
|
|
if (oldFile.size == newFile.size) {
|
|
this._onDidRename.fire({
|
|
oldUri: vscode_uri_1.URI.file(path.join(root, oldFile.name)),
|
|
newUri: vscode_uri_1.URI.file(path.join(root, newFile.name))
|
|
});
|
|
}
|
|
}
|
|
});
|
|
this.disposables.push(disposable);
|
|
return disposable;
|
|
}
|
|
dispose() {
|
|
util_1.disposeAll(this.disposables);
|
|
}
|
|
}
|
|
exports.default = FileSystemWatcher;
|
|
//# sourceMappingURL=fileSystemWatcher.js.map
|
|
|
|
/***/ }),
|
|
/* 215 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const os_1 = tslib_1.__importDefault(__webpack_require__(56));
|
|
const fs_1 = tslib_1.__importDefault(__webpack_require__(55));
|
|
const util_1 = tslib_1.__importDefault(__webpack_require__(40));
|
|
const mkdirp_1 = tslib_1.__importDefault(__webpack_require__(179));
|
|
const isWindows = process.platform == 'win32';
|
|
const root = isWindows ? path_1.default.join(os_1.default.homedir(), 'AppData/Local/coc') : path_1.default.join(os_1.default.homedir(), '.config/coc');
|
|
/**
|
|
* Mru - manage string items as lines in mru file.
|
|
*/
|
|
class Mru {
|
|
/**
|
|
* @param {string} name unique name
|
|
* @param {string} base? optional directory name, default to config root of coc.nvim
|
|
*/
|
|
constructor(name, base) {
|
|
this.name = name;
|
|
this.file = path_1.default.join(base || root, name);
|
|
}
|
|
/**
|
|
* Load iems from mru file
|
|
*/
|
|
async load() {
|
|
let dir = path_1.default.dirname(this.file);
|
|
try {
|
|
mkdirp_1.default.sync(dir);
|
|
if (!fs_1.default.existsSync(this.file)) {
|
|
fs_1.default.writeFileSync(this.file, '', 'utf8');
|
|
}
|
|
let content = await util_1.default.promisify(fs_1.default.readFile)(this.file, 'utf8');
|
|
content = content.trim();
|
|
return content.length ? content.trim().split('\n') : [];
|
|
}
|
|
catch (e) {
|
|
return [];
|
|
}
|
|
}
|
|
/**
|
|
* Add item to mru file.
|
|
*/
|
|
async add(item) {
|
|
let items = await this.load();
|
|
let idx = items.indexOf(item);
|
|
if (idx !== -1)
|
|
items.splice(idx, 1);
|
|
items.unshift(item);
|
|
fs_1.default.writeFileSync(this.file, items.join('\n'), 'utf8');
|
|
}
|
|
/**
|
|
* Remove item from mru file.
|
|
*/
|
|
async remove(item) {
|
|
let items = await this.load();
|
|
let idx = items.indexOf(item);
|
|
if (idx !== -1) {
|
|
items.splice(idx, 1);
|
|
fs_1.default.writeFileSync(this.file, items.join('\n'), 'utf8');
|
|
}
|
|
}
|
|
/**
|
|
* Remove the data file.
|
|
*/
|
|
async clean() {
|
|
try {
|
|
await util_1.default.promisify(fs_1.default.unlink)(this.file);
|
|
}
|
|
catch (e) {
|
|
// noop
|
|
}
|
|
}
|
|
}
|
|
exports.default = Mru;
|
|
//# sourceMappingURL=mru.js.map
|
|
|
|
/***/ }),
|
|
/* 216 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const util_1 = __webpack_require__(174);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)("outpubChannel");
|
|
class BufferChannel {
|
|
constructor(name, nvim) {
|
|
this.name = name;
|
|
this.nvim = nvim;
|
|
this._content = '';
|
|
this.disposables = [];
|
|
this._showing = false;
|
|
this.promise = Promise.resolve(void 0);
|
|
}
|
|
get content() {
|
|
return this._content;
|
|
}
|
|
async _append(value, isLine) {
|
|
let { buffer } = this;
|
|
if (!buffer)
|
|
return;
|
|
try {
|
|
if (isLine) {
|
|
await buffer.append(value.split('\n'));
|
|
}
|
|
else {
|
|
let last = await this.nvim.call('getbufline', [buffer.id, '$']);
|
|
let content = last + value;
|
|
if (this.buffer) {
|
|
await buffer.setLines(content.split('\n'), {
|
|
start: -2,
|
|
end: -1,
|
|
strictIndexing: false
|
|
});
|
|
}
|
|
}
|
|
}
|
|
catch (e) {
|
|
logger.error(`Error on append output:`, e);
|
|
}
|
|
}
|
|
append(value) {
|
|
this._content += value;
|
|
this.promise = this.promise.then(() => {
|
|
return this._append(value, false);
|
|
});
|
|
}
|
|
appendLine(value) {
|
|
this._content += value + '\n';
|
|
this.promise = this.promise.then(() => {
|
|
return this._append(value, true);
|
|
});
|
|
}
|
|
clear() {
|
|
this._content = '';
|
|
let { buffer } = this;
|
|
if (buffer) {
|
|
Promise.resolve(buffer.setLines([], {
|
|
start: 0,
|
|
end: -1,
|
|
strictIndexing: false
|
|
})).catch(_e => {
|
|
// noop
|
|
});
|
|
}
|
|
}
|
|
hide() {
|
|
let { nvim, buffer } = this;
|
|
if (buffer)
|
|
nvim.command(`silent! bd! ${buffer.id}`, true);
|
|
}
|
|
dispose() {
|
|
this.hide();
|
|
this._content = '';
|
|
util_1.disposeAll(this.disposables);
|
|
}
|
|
get buffer() {
|
|
let doc = workspace_1.default.getDocument(`output:///${this.name}`);
|
|
return doc ? doc.buffer : null;
|
|
}
|
|
async openBuffer(preserveFocus) {
|
|
let { nvim, buffer } = this;
|
|
if (buffer) {
|
|
let loaded = await nvim.call('bufloaded', buffer.id);
|
|
if (!loaded)
|
|
buffer = null;
|
|
}
|
|
if (!buffer) {
|
|
await nvim.command(`belowright vs output:///${this.name}`);
|
|
}
|
|
else {
|
|
// check shown
|
|
let wnr = await nvim.call('bufwinnr', buffer.id);
|
|
if (wnr != -1)
|
|
return;
|
|
await nvim.command(`vert belowright sb ${buffer.id}`);
|
|
}
|
|
if (preserveFocus) {
|
|
await nvim.command('wincmd p');
|
|
}
|
|
}
|
|
show(preserveFocus) {
|
|
if (this._showing)
|
|
return;
|
|
this._showing = true;
|
|
this.openBuffer(preserveFocus).then(() => {
|
|
this._showing = false;
|
|
}, () => {
|
|
this._showing = false;
|
|
});
|
|
}
|
|
}
|
|
exports.default = BufferChannel;
|
|
//# sourceMappingURL=outputChannel.js.map
|
|
|
|
/***/ }),
|
|
/* 217 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const util_1 = __webpack_require__(174);
|
|
const fs_1 = __webpack_require__(200);
|
|
const decorator_1 = __webpack_require__(218);
|
|
const logger = __webpack_require__(186)('model-resolver');
|
|
class Resolver {
|
|
get nodeFolder() {
|
|
if (!util_1.executable('npm'))
|
|
return Promise.resolve('');
|
|
return util_1.runCommand('npm --loglevel silent root -g', {}, 3000).then(root => {
|
|
return root.trim();
|
|
});
|
|
}
|
|
get yarnFolder() {
|
|
if (!util_1.executable('yarnpkg'))
|
|
return Promise.resolve('');
|
|
return util_1.runCommand('yarnpkg global dir', {}, 3000).then(root => {
|
|
return path_1.default.join(root.trim(), 'node_modules');
|
|
});
|
|
}
|
|
async resolveModule(mod) {
|
|
let nodeFolder = await this.nodeFolder;
|
|
let yarnFolder = await this.yarnFolder;
|
|
if (yarnFolder) {
|
|
let s = await fs_1.statAsync(path_1.default.join(yarnFolder, mod, 'package.json'));
|
|
if (s && s.isFile())
|
|
return path_1.default.join(yarnFolder, mod);
|
|
}
|
|
if (nodeFolder) {
|
|
let s = await fs_1.statAsync(path_1.default.join(nodeFolder, mod, 'package.json'));
|
|
if (s && s.isFile())
|
|
return path_1.default.join(nodeFolder, mod);
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
tslib_1.__decorate([
|
|
decorator_1.memorize
|
|
], Resolver.prototype, "nodeFolder", null);
|
|
tslib_1.__decorate([
|
|
decorator_1.memorize
|
|
], Resolver.prototype, "yarnFolder", null);
|
|
exports.default = Resolver;
|
|
//# sourceMappingURL=resolver.js.map
|
|
|
|
/***/ }),
|
|
/* 218 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const logger = __webpack_require__(186)('util-decorator');
|
|
function memorize(_target, key, descriptor) {
|
|
let fn = descriptor.get;
|
|
if (typeof fn !== 'function')
|
|
return;
|
|
let memoKey = '$' + key;
|
|
descriptor.get = function (...args) {
|
|
if (this.hasOwnProperty(memoKey))
|
|
return Promise.resolve(this[memoKey]);
|
|
return new Promise((resolve, reject) => {
|
|
Promise.resolve(fn.apply(this, args)).then(res => {
|
|
this[memoKey] = res;
|
|
resolve(res);
|
|
}, e => {
|
|
reject(e);
|
|
});
|
|
});
|
|
};
|
|
}
|
|
exports.memorize = memorize;
|
|
//# sourceMappingURL=decorator.js.map
|
|
|
|
/***/ }),
|
|
/* 219 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const uuidv1 = __webpack_require__(220);
|
|
const logger = __webpack_require__(186)('model-status');
|
|
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
class StatusLine {
|
|
constructor(nvim) {
|
|
this.nvim = nvim;
|
|
this.items = new Map();
|
|
this.shownIds = new Set();
|
|
this._text = '';
|
|
this.interval = setInterval(() => {
|
|
this.setStatusText().logError();
|
|
}, 100);
|
|
}
|
|
dispose() {
|
|
clearInterval(this.interval);
|
|
}
|
|
createStatusBarItem(priority = 0, isProgress = false) {
|
|
let uid = uuidv1();
|
|
let item = {
|
|
text: '',
|
|
priority,
|
|
isProgress,
|
|
show: () => {
|
|
this.shownIds.add(uid);
|
|
},
|
|
hide: () => {
|
|
this.shownIds.delete(uid);
|
|
},
|
|
dispose: () => {
|
|
this.shownIds.delete(uid);
|
|
this.items.delete(uid);
|
|
}
|
|
};
|
|
this.items.set(uid, item);
|
|
return item;
|
|
}
|
|
getText() {
|
|
if (this.shownIds.size == 0)
|
|
return '';
|
|
let d = new Date();
|
|
let idx = Math.floor(d.getMilliseconds() / 100);
|
|
let text = '';
|
|
let items = [];
|
|
for (let [id, item] of this.items) {
|
|
if (this.shownIds.has(id)) {
|
|
items.push(item);
|
|
}
|
|
}
|
|
items.sort((a, b) => a.priority - b.priority);
|
|
for (let item of items) {
|
|
if (!item.isProgress) {
|
|
text = `${text} ${item.text}`;
|
|
}
|
|
else {
|
|
text = `${text} ${frames[idx]} ${item.text}`;
|
|
}
|
|
}
|
|
return text;
|
|
}
|
|
async setStatusText() {
|
|
let text = this.getText();
|
|
let { nvim } = this;
|
|
if (text != this._text) {
|
|
this._text = text;
|
|
nvim.pauseNotification();
|
|
this.nvim.setVar('coc_status', text, true);
|
|
this.nvim.command('redraws', true);
|
|
this.nvim.call('coc#util#do_autocmd', ['CocStatusChange'], true);
|
|
await nvim.resumeNotification(false, true);
|
|
}
|
|
}
|
|
}
|
|
exports.default = StatusLine;
|
|
//# sourceMappingURL=status.js.map
|
|
|
|
/***/ }),
|
|
/* 220 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var rng = __webpack_require__(221);
|
|
var bytesToUuid = __webpack_require__(222);
|
|
|
|
// **`v1()` - Generate time-based UUID**
|
|
//
|
|
// Inspired by https://github.com/LiosK/UUID.js
|
|
// and http://docs.python.org/library/uuid.html
|
|
|
|
var _nodeId;
|
|
var _clockseq;
|
|
|
|
// Previous uuid creation time
|
|
var _lastMSecs = 0;
|
|
var _lastNSecs = 0;
|
|
|
|
// See https://github.com/broofa/node-uuid for API details
|
|
function v1(options, buf, offset) {
|
|
var i = buf && offset || 0;
|
|
var b = buf || [];
|
|
|
|
options = options || {};
|
|
var node = options.node || _nodeId;
|
|
var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
|
|
|
|
// node and clockseq need to be initialized to random values if they're not
|
|
// specified. We do this lazily to minimize issues related to insufficient
|
|
// system entropy. See #189
|
|
if (node == null || clockseq == null) {
|
|
var seedBytes = rng();
|
|
if (node == null) {
|
|
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
|
|
node = _nodeId = [
|
|
seedBytes[0] | 0x01,
|
|
seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]
|
|
];
|
|
}
|
|
if (clockseq == null) {
|
|
// Per 4.2.2, randomize (14 bit) clockseq
|
|
clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
|
|
}
|
|
}
|
|
|
|
// UUID timestamps are 100 nano-second units since the Gregorian epoch,
|
|
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
|
|
// time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
|
|
// (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
|
|
var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();
|
|
|
|
// Per 4.2.1.2, use count of uuid's generated during the current clock
|
|
// cycle to simulate higher resolution clock
|
|
var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;
|
|
|
|
// Time since last uuid creation (in msecs)
|
|
var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
|
|
|
|
// Per 4.2.1.2, Bump clockseq on clock regression
|
|
if (dt < 0 && options.clockseq === undefined) {
|
|
clockseq = clockseq + 1 & 0x3fff;
|
|
}
|
|
|
|
// Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
|
|
// time interval
|
|
if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
|
|
nsecs = 0;
|
|
}
|
|
|
|
// Per 4.2.1.2 Throw error if too many uuids are requested
|
|
if (nsecs >= 10000) {
|
|
throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
|
|
}
|
|
|
|
_lastMSecs = msecs;
|
|
_lastNSecs = nsecs;
|
|
_clockseq = clockseq;
|
|
|
|
// Per 4.1.4 - Convert from unix epoch to Gregorian epoch
|
|
msecs += 12219292800000;
|
|
|
|
// `time_low`
|
|
var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
|
|
b[i++] = tl >>> 24 & 0xff;
|
|
b[i++] = tl >>> 16 & 0xff;
|
|
b[i++] = tl >>> 8 & 0xff;
|
|
b[i++] = tl & 0xff;
|
|
|
|
// `time_mid`
|
|
var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
|
|
b[i++] = tmh >>> 8 & 0xff;
|
|
b[i++] = tmh & 0xff;
|
|
|
|
// `time_high_and_version`
|
|
b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
|
|
b[i++] = tmh >>> 16 & 0xff;
|
|
|
|
// `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
|
|
b[i++] = clockseq >>> 8 | 0x80;
|
|
|
|
// `clock_seq_low`
|
|
b[i++] = clockseq & 0xff;
|
|
|
|
// `node`
|
|
for (var n = 0; n < 6; ++n) {
|
|
b[i + n] = node[n];
|
|
}
|
|
|
|
return buf ? buf : bytesToUuid(b);
|
|
}
|
|
|
|
module.exports = v1;
|
|
|
|
|
|
/***/ }),
|
|
/* 221 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// Unique ID creation requires a high quality random # generator. In node.js
|
|
// this is pretty straight-forward - we use the crypto API.
|
|
|
|
var crypto = __webpack_require__(159);
|
|
|
|
module.exports = function nodeRNG() {
|
|
return crypto.randomBytes(16);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 222 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* Convert array of 16 byte values to UUID string format of the form:
|
|
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
|
*/
|
|
var byteToHex = [];
|
|
for (var i = 0; i < 256; ++i) {
|
|
byteToHex[i] = (i + 0x100).toString(16).substr(1);
|
|
}
|
|
|
|
function bytesToUuid(buf, offset) {
|
|
var i = offset || 0;
|
|
var bth = byteToHex;
|
|
// join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
|
|
return ([bth[buf[i++]], bth[buf[i++]],
|
|
bth[buf[i++]], bth[buf[i++]], '-',
|
|
bth[buf[i++]], bth[buf[i++]], '-',
|
|
bth[buf[i++]], bth[buf[i++]], '-',
|
|
bth[buf[i++]], bth[buf[i++]], '-',
|
|
bth[buf[i++]], bth[buf[i++]],
|
|
bth[buf[i++]], bth[buf[i++]],
|
|
bth[buf[i++]], bth[buf[i++]]]).join('');
|
|
}
|
|
|
|
module.exports = bytesToUuid;
|
|
|
|
|
|
/***/ }),
|
|
/* 223 */
|
|
/***/ (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__(148));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const util_1 = __webpack_require__(174);
|
|
/**
|
|
* Controls long running task started by vim.
|
|
* Useful to keep the task running after CocRestart.
|
|
*
|
|
* @public
|
|
*/
|
|
class Task {
|
|
/**
|
|
* @param {Neovim} nvim
|
|
* @param {string} id unique id
|
|
*/
|
|
constructor(nvim, id) {
|
|
this.nvim = nvim;
|
|
this.id = id;
|
|
this.disposables = [];
|
|
this._onExit = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onStderr = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onStdout = new vscode_languageserver_protocol_1.Emitter();
|
|
this.onExit = this._onExit.event;
|
|
this.onStdout = this._onStdout.event;
|
|
this.onStderr = this._onStderr.event;
|
|
events_1.default.on('TaskExit', (id, code) => {
|
|
if (id == this.id) {
|
|
this._onExit.fire(code);
|
|
}
|
|
}, null, this.disposables);
|
|
events_1.default.on('TaskStderr', (id, lines) => {
|
|
if (id == this.id) {
|
|
this._onStderr.fire(lines);
|
|
}
|
|
}, null, this.disposables);
|
|
let stdout = [];
|
|
let timer;
|
|
events_1.default.on('TaskStdout', (id, lines) => {
|
|
if (id == this.id) {
|
|
if (timer)
|
|
clearTimeout(timer);
|
|
stdout.push(...lines);
|
|
timer = setTimeout(() => {
|
|
this._onStdout.fire(stdout);
|
|
stdout = [];
|
|
}, 100);
|
|
}
|
|
}, null, this.disposables);
|
|
}
|
|
/**
|
|
* Start task, task will be restarted when already running.
|
|
*
|
|
* @param {TaskOptions} opts
|
|
* @returns {Promise<boolean>}
|
|
*/
|
|
async start(opts) {
|
|
let { nvim } = this;
|
|
return await nvim.call('coc#task#start', [this.id, opts]);
|
|
}
|
|
/**
|
|
* Stop task by SIGTERM or SIGKILL
|
|
*/
|
|
async stop() {
|
|
let { nvim } = this;
|
|
await nvim.call('coc#task#stop', [this.id]);
|
|
}
|
|
/**
|
|
* Check if the task is running.
|
|
*/
|
|
get running() {
|
|
let { nvim } = this;
|
|
return nvim.call('coc#task#running', [this.id]);
|
|
}
|
|
/**
|
|
* Stop task and dispose all events.
|
|
*/
|
|
dispose() {
|
|
let { nvim } = this;
|
|
nvim.call('coc#task#stop', [this.id], true);
|
|
this._onStdout.dispose();
|
|
this._onStderr.dispose();
|
|
this._onExit.dispose();
|
|
util_1.disposeAll(this.disposables);
|
|
}
|
|
}
|
|
exports.default = Task;
|
|
//# sourceMappingURL=task.js.map
|
|
|
|
/***/ }),
|
|
/* 224 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const logger = __webpack_require__(186)('model-terminal');
|
|
class TerminalModel {
|
|
constructor(cmd, args, nvim, _name) {
|
|
this.cmd = cmd;
|
|
this.args = args;
|
|
this.nvim = nvim;
|
|
this._name = _name;
|
|
this.pid = 0;
|
|
}
|
|
async start(cwd, env) {
|
|
let { nvim } = this;
|
|
let cmd = [this.cmd, ...this.args];
|
|
let [bufnr, pid] = await nvim.call('coc#terminal#start', [cmd, cwd, env || {}]);
|
|
this.bufnr = bufnr;
|
|
this.pid = pid;
|
|
}
|
|
get name() {
|
|
return this._name || this.cmd;
|
|
}
|
|
get processId() {
|
|
return Promise.resolve(this.pid);
|
|
}
|
|
sendText(text, addNewLine = true) {
|
|
if (!this.bufnr)
|
|
return;
|
|
this.nvim.call('coc#terminal#send', [this.bufnr, text, addNewLine], true);
|
|
}
|
|
async show(preserveFocus) {
|
|
let { bufnr, nvim } = this;
|
|
if (!bufnr)
|
|
return;
|
|
let [loaded, winid] = await nvim.eval(`[bufloaded(${bufnr}),bufwinid(${bufnr})]`);
|
|
if (!loaded)
|
|
return false;
|
|
nvim.pauseNotification();
|
|
if (winid == -1) {
|
|
nvim.command(`below ${bufnr}sb`, true);
|
|
nvim.command('resize 8', true);
|
|
nvim.call('coc#util#do_autocmd', ['CocTerminalOpen'], true);
|
|
}
|
|
else {
|
|
nvim.call('win_gotoid', [winid], true);
|
|
}
|
|
nvim.command('normal! G', true);
|
|
if (preserveFocus) {
|
|
nvim.command('wincmd p', true);
|
|
}
|
|
await nvim.resumeNotification();
|
|
return true;
|
|
}
|
|
async hide() {
|
|
let { bufnr, nvim } = this;
|
|
if (!bufnr)
|
|
return;
|
|
let winnr = await nvim.call('bufwinnr', bufnr);
|
|
if (winnr == -1)
|
|
return;
|
|
await nvim.command(`${winnr}close!`);
|
|
}
|
|
dispose() {
|
|
let { bufnr, nvim } = this;
|
|
if (!bufnr)
|
|
return;
|
|
nvim.call('coc#terminal#close', [bufnr], true);
|
|
}
|
|
}
|
|
exports.default = TerminalModel;
|
|
//# sourceMappingURL=terminal.js.map
|
|
|
|
/***/ }),
|
|
/* 225 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const util_1 = __webpack_require__(174);
|
|
const logger = __webpack_require__(186)('willSaveHandler');
|
|
class WillSaveUntilHandler {
|
|
constructor(workspace) {
|
|
this.workspace = workspace;
|
|
this.callbacks = [];
|
|
}
|
|
get nvim() {
|
|
return this.workspace.nvim;
|
|
}
|
|
addCallback(callback, thisArg, clientId) {
|
|
let fn = (event) => {
|
|
let { nvim, workspace } = this;
|
|
let ev = Object.assign({}, event);
|
|
return new Promise(resolve => {
|
|
let called = false;
|
|
ev.waitUntil = (thenable) => {
|
|
called = true;
|
|
let { document } = ev;
|
|
let timer = setTimeout(() => {
|
|
workspace.showMessage(`${clientId} will save operation timeout after 0.5s`, 'warning');
|
|
resolve(null);
|
|
}, 500);
|
|
Promise.resolve(thenable).then((edits) => {
|
|
clearTimeout(timer);
|
|
let doc = workspace.getDocument(document.uri);
|
|
if (doc && edits && vscode_languageserver_protocol_1.TextEdit.is(edits[0])) {
|
|
doc.applyEdits(nvim, edits).then(() => {
|
|
// make sure server received ChangedText
|
|
setTimeout(resolve, 50);
|
|
}, e => {
|
|
logger.error(e);
|
|
workspace.showMessage(`${clientId} error on applyEdits ${e.message}`, 'error');
|
|
resolve();
|
|
});
|
|
}
|
|
else {
|
|
resolve();
|
|
}
|
|
}, e => {
|
|
clearTimeout(timer);
|
|
logger.error(`${clientId} error on willSaveUntil ${e.message}`, 'error');
|
|
resolve();
|
|
});
|
|
};
|
|
callback.call(thisArg, ev);
|
|
if (!called) {
|
|
resolve();
|
|
}
|
|
});
|
|
};
|
|
this.callbacks.push(fn);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
let idx = this.callbacks.indexOf(fn);
|
|
if (idx != -1) {
|
|
this.callbacks.splice(idx, 1);
|
|
}
|
|
});
|
|
}
|
|
get hasCallback() {
|
|
let { callbacks } = this;
|
|
return callbacks.length > 0;
|
|
}
|
|
async handeWillSaveUntil(event) {
|
|
let { callbacks, workspace } = this;
|
|
let { document } = event;
|
|
if (!callbacks.length)
|
|
return;
|
|
let doc = workspace.getDocument(document.uri);
|
|
if (!doc)
|
|
return;
|
|
let now = Date.now();
|
|
if (doc.dirty) {
|
|
doc.forceSync();
|
|
await util_1.wait(60);
|
|
}
|
|
for (let fn of callbacks) {
|
|
event.document = doc.textDocument;
|
|
try {
|
|
await fn(event);
|
|
}
|
|
catch (e) {
|
|
logger.error(e);
|
|
}
|
|
}
|
|
logger.info(`Will save cost: ${Date.now() - now}`);
|
|
}
|
|
}
|
|
exports.default = WillSaveUntilHandler;
|
|
//# sourceMappingURL=willSaveHandler.js.map
|
|
|
|
/***/ }),
|
|
/* 226 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const minimatch_1 = tslib_1.__importDefault(__webpack_require__(201));
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
function score(selector, uri, languageId) {
|
|
if (Array.isArray(selector)) {
|
|
// array -> take max individual value
|
|
let ret = 0;
|
|
for (const filter of selector) {
|
|
const value = score(filter, uri, languageId);
|
|
if (value === 10) {
|
|
return value; // already at the highest
|
|
}
|
|
if (value > ret) {
|
|
ret = value;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
else if (typeof selector === 'string') {
|
|
// short-hand notion, desugars to
|
|
// 'fooLang' -> { language: 'fooLang'}
|
|
// '*' -> { language: '*' }
|
|
if (selector === '*') {
|
|
return 5;
|
|
}
|
|
else if (selector === languageId) {
|
|
return 10;
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
else if (selector) {
|
|
let u = vscode_uri_1.URI.parse(uri);
|
|
// filter -> select accordingly, use defaults for scheme
|
|
const { language, pattern, scheme } = selector;
|
|
let ret = 0;
|
|
if (scheme) {
|
|
if (scheme === u.scheme) {
|
|
ret = 5;
|
|
}
|
|
else if (scheme === '*') {
|
|
ret = 3;
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
if (language) {
|
|
if (language === languageId) {
|
|
ret = 10;
|
|
}
|
|
else if (language === '*') {
|
|
ret = Math.max(ret, 5);
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
if (pattern) {
|
|
if (pattern === u.fsPath || minimatch_1.default(u.fsPath, pattern, { dot: true })) {
|
|
ret = 5;
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
exports.score = score;
|
|
//# sourceMappingURL=match.js.map
|
|
|
|
/***/ }),
|
|
/* 227 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const fb_watchman_1 = tslib_1.__importDefault(__webpack_require__(228));
|
|
const os_1 = tslib_1.__importDefault(__webpack_require__(56));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const uuidv1 = __webpack_require__(220);
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const minimatch_1 = tslib_1.__importDefault(__webpack_require__(201));
|
|
const logger = __webpack_require__(186)('watchman');
|
|
const requiredCapabilities = ['relative_root', 'cmd-watch-project', 'wildmatch'];
|
|
const clientsMap = new Map();
|
|
/**
|
|
* Watchman wrapper for fb-watchman client
|
|
*
|
|
* @public
|
|
*/
|
|
class Watchman {
|
|
constructor(binaryPath, channel) {
|
|
this.channel = channel;
|
|
this._disposed = false;
|
|
this.client = new fb_watchman_1.default.Client({
|
|
watchmanBinaryPath: binaryPath
|
|
});
|
|
this.client.setMaxListeners(300);
|
|
}
|
|
checkCapability() {
|
|
let { client } = this;
|
|
return new Promise((resolve, reject) => {
|
|
client.capabilityCheck({
|
|
optional: [],
|
|
required: requiredCapabilities
|
|
}, (error, resp) => {
|
|
if (error)
|
|
return reject(error);
|
|
let { capabilities } = resp;
|
|
for (let key of Object.keys(capabilities)) {
|
|
if (!capabilities[key])
|
|
return resolve(false);
|
|
}
|
|
resolve(true);
|
|
});
|
|
});
|
|
}
|
|
async watchProject(root) {
|
|
try {
|
|
let resp = await this.command(['watch-project', root]);
|
|
let { watch, warning, relative_path } = resp;
|
|
if (warning)
|
|
logger.warn(warning);
|
|
this.watch = watch;
|
|
this.relative_path = relative_path;
|
|
logger.info(`watchman watching project: ${root}`);
|
|
this.appendOutput(`watchman watching project: ${root}`);
|
|
}
|
|
catch (e) {
|
|
logger.error(e);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
command(args) {
|
|
return new Promise((resolve, reject) => {
|
|
this.client.command(args, (error, resp) => {
|
|
if (error)
|
|
return reject(error);
|
|
resolve(resp);
|
|
});
|
|
});
|
|
}
|
|
async subscribe(globPattern, cb) {
|
|
let { watch, relative_path } = this;
|
|
if (!watch) {
|
|
this.appendOutput(`watchman not watching: ${watch}`, 'Error');
|
|
return null;
|
|
}
|
|
let { clock } = await this.command(['clock', watch]);
|
|
let uid = uuidv1();
|
|
let sub = {
|
|
expression: ['allof', ['match', '**/*', 'wholename']],
|
|
fields: ['name', 'size', 'exists', 'type', 'mtime_ms', 'ctime_ms'],
|
|
since: clock,
|
|
};
|
|
let root = watch;
|
|
if (relative_path) {
|
|
sub.relative_root = relative_path;
|
|
root = path_1.default.join(watch, relative_path);
|
|
}
|
|
let { subscribe } = await this.command(['subscribe', watch, uid, sub]);
|
|
if (global.hasOwnProperty('__TEST__'))
|
|
global.subscribe = subscribe;
|
|
this.appendOutput(`subscribing "${globPattern}" in ${root}`);
|
|
this.client.on('subscription', resp => {
|
|
if (!resp || resp.subscription != uid)
|
|
return;
|
|
let { files } = resp;
|
|
files = files.filter(f => f.type == 'f');
|
|
if (!files || !files.length || !minimatch_1.default(files[0].name, globPattern))
|
|
return;
|
|
let ev = Object.assign({}, resp);
|
|
if (this.relative_path)
|
|
ev.root = path_1.default.resolve(resp.root, this.relative_path);
|
|
// resp.root = this.relative_path
|
|
files.map(f => f.mtime_ms = +f.mtime_ms);
|
|
this.appendOutput(`file change detected: ${JSON.stringify(ev, null, 2)}`);
|
|
cb(ev);
|
|
});
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
return this.unsubscribe(subscribe);
|
|
});
|
|
}
|
|
unsubscribe(subscription) {
|
|
if (this._disposed)
|
|
return Promise.resolve();
|
|
let { watch } = this;
|
|
if (!watch)
|
|
return;
|
|
this.appendOutput(`unsubscribe "${subscription}" in: ${watch}`);
|
|
return this.command(['unsubscribe', watch, subscription]).catch(e => {
|
|
logger.error(e);
|
|
});
|
|
}
|
|
dispose() {
|
|
this._disposed = true;
|
|
this.client.removeAllListeners();
|
|
this.client.end();
|
|
}
|
|
appendOutput(message, type = "Info") {
|
|
if (this.channel) {
|
|
this.channel.appendLine(`[${type} - ${(new Date().toLocaleTimeString())}] ${message}`);
|
|
}
|
|
}
|
|
static dispose() {
|
|
for (let promise of clientsMap.values()) {
|
|
promise.then(client => {
|
|
client.dispose();
|
|
}, _e => {
|
|
// noop
|
|
});
|
|
}
|
|
}
|
|
static createClient(binaryPath, root, channel) {
|
|
if (root == os_1.default.homedir() || root == '/' || path_1.default.parse(root).base == root)
|
|
return null;
|
|
let client = clientsMap.get(root);
|
|
if (client)
|
|
return client;
|
|
let promise = new Promise(async (resolve, reject) => {
|
|
try {
|
|
let watchman = new Watchman(binaryPath, channel);
|
|
let valid = await watchman.checkCapability();
|
|
if (!valid)
|
|
return resolve(null);
|
|
let watching = await watchman.watchProject(root);
|
|
if (!watching)
|
|
return resolve(null);
|
|
resolve(watchman);
|
|
}
|
|
catch (e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
clientsMap.set(root, promise);
|
|
return promise;
|
|
}
|
|
}
|
|
exports.default = Watchman;
|
|
//# sourceMappingURL=watchman.js.map
|
|
|
|
/***/ }),
|
|
/* 228 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
/* Copyright 2014-present Facebook, Inc.
|
|
* Licensed under the Apache License, Version 2.0 */
|
|
|
|
|
|
|
|
var net = __webpack_require__(6);
|
|
var EE = __webpack_require__(49).EventEmitter;
|
|
var util = __webpack_require__(40);
|
|
var childProcess = __webpack_require__(175);
|
|
var bser = __webpack_require__(229);
|
|
|
|
// We'll emit the responses to these when they get sent down to us
|
|
var unilateralTags = ['subscription', 'log'];
|
|
|
|
/**
|
|
* @param options An object with the following optional keys:
|
|
* * 'watchmanBinaryPath' (string) Absolute path to the watchman binary.
|
|
* If not provided, the Client locates the binary using the PATH specified
|
|
* by the node child_process's default env.
|
|
*/
|
|
function Client(options) {
|
|
var self = this;
|
|
EE.call(this);
|
|
|
|
this.watchmanBinaryPath = 'watchman';
|
|
if (options && options.watchmanBinaryPath) {
|
|
this.watchmanBinaryPath = options.watchmanBinaryPath.trim();
|
|
};
|
|
this.commands = [];
|
|
}
|
|
util.inherits(Client, EE);
|
|
|
|
module.exports.Client = Client;
|
|
|
|
// Try to send the next queued command, if any
|
|
Client.prototype.sendNextCommand = function() {
|
|
if (this.currentCommand) {
|
|
// There's a command pending response, don't send this new one yet
|
|
return;
|
|
}
|
|
|
|
this.currentCommand = this.commands.shift();
|
|
if (!this.currentCommand) {
|
|
// No further commands are queued
|
|
return;
|
|
}
|
|
|
|
this.socket.write(bser.dumpToBuffer(this.currentCommand.cmd));
|
|
}
|
|
|
|
Client.prototype.cancelCommands = function(why) {
|
|
var error = new Error(why);
|
|
|
|
// Steal all pending commands before we start cancellation, in
|
|
// case something decides to schedule more commands
|
|
var cmds = this.commands;
|
|
this.commands = [];
|
|
|
|
if (this.currentCommand) {
|
|
cmds.unshift(this.currentCommand);
|
|
this.currentCommand = null;
|
|
}
|
|
|
|
// Synthesize an error condition for any commands that were queued
|
|
cmds.forEach(function(cmd) {
|
|
cmd.cb(error);
|
|
});
|
|
}
|
|
|
|
Client.prototype.connect = function() {
|
|
var self = this;
|
|
|
|
function makeSock(sockname) {
|
|
// bunser will decode the watchman BSER protocol for us
|
|
self.bunser = new bser.BunserBuf();
|
|
// For each decoded line:
|
|
self.bunser.on('value', function(obj) {
|
|
// Figure out if this is a unliteral response or if it is the
|
|
// response portion of a request-response sequence. At the time
|
|
// of writing, there are only two possible unilateral responses.
|
|
var unilateral = false;
|
|
for (var i = 0; i < unilateralTags.length; i++) {
|
|
var tag = unilateralTags[i];
|
|
if (tag in obj) {
|
|
unilateral = tag;
|
|
}
|
|
}
|
|
|
|
if (unilateral) {
|
|
self.emit(unilateral, obj);
|
|
} else if (self.currentCommand) {
|
|
var cmd = self.currentCommand;
|
|
self.currentCommand = null;
|
|
if ('error' in obj) {
|
|
var error = new Error(obj.error);
|
|
error.watchmanResponse = obj;
|
|
cmd.cb(error);
|
|
} else {
|
|
cmd.cb(null, obj);
|
|
}
|
|
}
|
|
|
|
// See if we can dispatch the next queued command, if any
|
|
self.sendNextCommand();
|
|
});
|
|
self.bunser.on('error', function(err) {
|
|
self.emit('error', err);
|
|
});
|
|
|
|
self.socket = net.createConnection(sockname);
|
|
self.socket.on('connect', function() {
|
|
self.connecting = false;
|
|
self.emit('connect');
|
|
self.sendNextCommand();
|
|
});
|
|
self.socket.on('error', function(err) {
|
|
self.connecting = false;
|
|
self.emit('error', err);
|
|
});
|
|
self.socket.on('data', function(buf) {
|
|
if (self.bunser) {
|
|
self.bunser.append(buf);
|
|
}
|
|
});
|
|
self.socket.on('end', function() {
|
|
self.socket = null;
|
|
self.bunser = null;
|
|
self.cancelCommands('The watchman connection was closed');
|
|
self.emit('end');
|
|
});
|
|
}
|
|
|
|
// triggers will export the sock path to the environment.
|
|
// If we're invoked in such a way, we can simply pick up the
|
|
// definition from the environment and avoid having to fork off
|
|
// a process to figure it out
|
|
if (process.env.WATCHMAN_SOCK) {
|
|
makeSock(process.env.WATCHMAN_SOCK);
|
|
return;
|
|
}
|
|
|
|
// We need to ask the client binary where to find it.
|
|
// This will cause the service to start for us if it isn't
|
|
// already running.
|
|
var args = ['--no-pretty', 'get-sockname'];
|
|
|
|
// We use the more elaborate spawn rather than exec because there
|
|
// are some error cases on Windows where process spawning can hang.
|
|
// It is desirable to pipe stderr directly to stderr live so that
|
|
// we can discover the problem.
|
|
var proc = null;
|
|
var spawnFailed = false;
|
|
|
|
function spawnError(error) {
|
|
if (spawnFailed) {
|
|
// For ENOENT, proc 'close' will also trigger with a negative code,
|
|
// let's suppress that second error.
|
|
return;
|
|
}
|
|
spawnFailed = true;
|
|
if (error.errno === 'EACCES') {
|
|
error.message = 'The Watchman CLI is installed but cannot ' +
|
|
'be spawned because of a permission problem';
|
|
} else if (error.errno === 'ENOENT') {
|
|
error.message = 'Watchman was not found in PATH. See ' +
|
|
'https://facebook.github.io/watchman/docs/install.html ' +
|
|
'for installation instructions';
|
|
}
|
|
console.error('Watchman: ', error.message);
|
|
self.emit('error', error);
|
|
}
|
|
|
|
try {
|
|
proc = childProcess.spawn(this.watchmanBinaryPath, args, {
|
|
stdio: ['ignore', 'pipe', 'pipe']
|
|
});
|
|
} catch (error) {
|
|
spawnError(error);
|
|
return;
|
|
}
|
|
|
|
var stdout = [];
|
|
var stderr = [];
|
|
proc.stdout.on('data', function(data) {
|
|
stdout.push(data);
|
|
});
|
|
proc.stderr.on('data', function(data) {
|
|
data = data.toString('utf8');
|
|
stderr.push(data);
|
|
console.error(data);
|
|
});
|
|
proc.on('error', function(error) {
|
|
spawnError(error);
|
|
});
|
|
|
|
proc.on('close', function (code, signal) {
|
|
if (code !== 0) {
|
|
spawnError(new Error(
|
|
self.watchmanBinaryPath + ' ' + args.join(' ') +
|
|
' returned with exit code=' + code + ', signal=' +
|
|
signal + ', stderr= ' + stderr.join('')));
|
|
return;
|
|
}
|
|
try {
|
|
var obj = JSON.parse(stdout.join(''));
|
|
if ('error' in obj) {
|
|
var error = new Error(obj.error);
|
|
error.watchmanResponse = obj;
|
|
self.emit('error', error);
|
|
return;
|
|
}
|
|
makeSock(obj.sockname);
|
|
} catch (e) {
|
|
self.emit('error', e);
|
|
}
|
|
});
|
|
}
|
|
|
|
Client.prototype.command = function(args, done) {
|
|
done = done || function() {};
|
|
|
|
// Queue up the command
|
|
this.commands.push({cmd: args, cb: done});
|
|
|
|
// Establish a connection if we don't already have one
|
|
if (!this.socket) {
|
|
if (!this.connecting) {
|
|
this.connecting = true;
|
|
this.connect();
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// If we're already connected and idle, try sending the command immediately
|
|
this.sendNextCommand();
|
|
}
|
|
|
|
var cap_versions = {
|
|
"cmd-watch-del-all": "3.1.1",
|
|
"cmd-watch-project": "3.1",
|
|
"relative_root": "3.3",
|
|
"term-dirname": "3.1",
|
|
"term-idirname": "3.1",
|
|
"wildmatch": "3.7",
|
|
}
|
|
|
|
// Compares a vs b, returns < 0 if a < b, > 0 if b > b, 0 if a == b
|
|
function vers_compare(a, b) {
|
|
a = a.split('.');
|
|
b = b.split('.');
|
|
for (var i = 0; i < 3; i++) {
|
|
var d = parseInt(a[i] || '0') - parseInt(b[i] || '0');
|
|
if (d != 0) {
|
|
return d;
|
|
}
|
|
}
|
|
return 0; // Equal
|
|
}
|
|
|
|
function have_cap(vers, name) {
|
|
if (name in cap_versions) {
|
|
return vers_compare(vers, cap_versions[name]) >= 0;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// This is a helper that we expose for testing purposes
|
|
Client.prototype._synthesizeCapabilityCheck = function(
|
|
resp, optional, required) {
|
|
resp.capabilities = {}
|
|
var version = resp.version;
|
|
optional.forEach(function (name) {
|
|
resp.capabilities[name] = have_cap(version, name);
|
|
});
|
|
required.forEach(function (name) {
|
|
var have = have_cap(version, name);
|
|
resp.capabilities[name] = have;
|
|
if (!have) {
|
|
resp.error = 'client required capability `' + name +
|
|
'` is not supported by this server';
|
|
}
|
|
});
|
|
return resp;
|
|
}
|
|
|
|
Client.prototype.capabilityCheck = function(caps, done) {
|
|
var optional = caps.optional || [];
|
|
var required = caps.required || [];
|
|
var self = this;
|
|
this.command(['version', {
|
|
optional: optional,
|
|
required: required
|
|
}], function (error, resp) {
|
|
if (error) {
|
|
done(error);
|
|
return;
|
|
}
|
|
if (!('capabilities' in resp)) {
|
|
// Server doesn't support capabilities, so we need to
|
|
// synthesize the results based on the version
|
|
resp = self._synthesizeCapabilityCheck(resp, optional, required);
|
|
if (resp.error) {
|
|
error = new Error(resp.error);
|
|
error.watchmanResponse = resp;
|
|
done(error);
|
|
return;
|
|
}
|
|
}
|
|
done(null, resp);
|
|
});
|
|
}
|
|
|
|
// Close the connection to the service
|
|
Client.prototype.end = function() {
|
|
this.cancelCommands('The client was ended');
|
|
if (this.socket) {
|
|
this.socket.end();
|
|
this.socket = null;
|
|
}
|
|
this.bunser = null;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 229 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* Copyright 2015-present Facebook, Inc.
|
|
* Licensed under the Apache License, Version 2.0 */
|
|
|
|
var EE = __webpack_require__(49).EventEmitter;
|
|
var util = __webpack_require__(40);
|
|
var os = __webpack_require__(56);
|
|
var assert = __webpack_require__(101);
|
|
var Int64 = __webpack_require__(230);
|
|
|
|
// BSER uses the local endianness to reduce byte swapping overheads
|
|
// (the protocol is expressly local IPC only). We need to tell node
|
|
// to use the native endianness when reading various native values.
|
|
var isBigEndian = os.endianness() == 'BE';
|
|
|
|
// Find the next power-of-2 >= size
|
|
function nextPow2(size) {
|
|
return Math.pow(2, Math.ceil(Math.log(size) / Math.LN2));
|
|
}
|
|
|
|
// Expandable buffer that we can provide a size hint for
|
|
function Accumulator(initsize) {
|
|
this.buf = new Buffer(nextPow2(initsize || 8192));
|
|
this.readOffset = 0;
|
|
this.writeOffset = 0;
|
|
}
|
|
// For testing
|
|
exports.Accumulator = Accumulator
|
|
|
|
// How much we can write into this buffer without allocating
|
|
Accumulator.prototype.writeAvail = function() {
|
|
return this.buf.length - this.writeOffset;
|
|
}
|
|
|
|
// How much we can read
|
|
Accumulator.prototype.readAvail = function() {
|
|
return this.writeOffset - this.readOffset;
|
|
}
|
|
|
|
// Ensure that we have enough space for size bytes
|
|
Accumulator.prototype.reserve = function(size) {
|
|
if (size < this.writeAvail()) {
|
|
return;
|
|
}
|
|
|
|
// If we can make room by shunting down, do so
|
|
if (this.readOffset > 0) {
|
|
this.buf.copy(this.buf, 0, this.readOffset, this.writeOffset);
|
|
this.writeOffset -= this.readOffset;
|
|
this.readOffset = 0;
|
|
}
|
|
|
|
// If we made enough room, no need to allocate more
|
|
if (size < this.writeAvail()) {
|
|
return;
|
|
}
|
|
|
|
// Allocate a replacement and copy it in
|
|
var buf = new Buffer(nextPow2(this.buf.length + size - this.writeAvail()));
|
|
this.buf.copy(buf);
|
|
this.buf = buf;
|
|
}
|
|
|
|
// Append buffer or string. Will resize as needed
|
|
Accumulator.prototype.append = function(buf) {
|
|
if (Buffer.isBuffer(buf)) {
|
|
this.reserve(buf.length);
|
|
buf.copy(this.buf, this.writeOffset, 0, buf.length);
|
|
this.writeOffset += buf.length;
|
|
} else {
|
|
var size = Buffer.byteLength(buf);
|
|
this.reserve(size);
|
|
this.buf.write(buf, this.writeOffset);
|
|
this.writeOffset += size;
|
|
}
|
|
}
|
|
|
|
Accumulator.prototype.assertReadableSize = function(size) {
|
|
if (this.readAvail() < size) {
|
|
throw new Error("wanted to read " + size +
|
|
" bytes but only have " + this.readAvail());
|
|
}
|
|
}
|
|
|
|
Accumulator.prototype.peekString = function(size) {
|
|
this.assertReadableSize(size);
|
|
return this.buf.toString('utf-8', this.readOffset, this.readOffset + size);
|
|
}
|
|
|
|
Accumulator.prototype.readString = function(size) {
|
|
var str = this.peekString(size);
|
|
this.readOffset += size;
|
|
return str;
|
|
}
|
|
|
|
Accumulator.prototype.peekInt = function(size) {
|
|
this.assertReadableSize(size);
|
|
switch (size) {
|
|
case 1:
|
|
return this.buf.readInt8(this.readOffset, size);
|
|
case 2:
|
|
return isBigEndian ?
|
|
this.buf.readInt16BE(this.readOffset, size) :
|
|
this.buf.readInt16LE(this.readOffset, size);
|
|
case 4:
|
|
return isBigEndian ?
|
|
this.buf.readInt32BE(this.readOffset, size) :
|
|
this.buf.readInt32LE(this.readOffset, size);
|
|
case 8:
|
|
var big = this.buf.slice(this.readOffset, this.readOffset + 8);
|
|
if (isBigEndian) {
|
|
// On a big endian system we can simply pass the buffer directly
|
|
return new Int64(big);
|
|
}
|
|
// Otherwise we need to byteswap
|
|
return new Int64(byteswap64(big));
|
|
default:
|
|
throw new Error("invalid integer size " + size);
|
|
}
|
|
}
|
|
|
|
Accumulator.prototype.readInt = function(bytes) {
|
|
var ival = this.peekInt(bytes);
|
|
if (ival instanceof Int64 && isFinite(ival.valueOf())) {
|
|
ival = ival.valueOf();
|
|
}
|
|
this.readOffset += bytes;
|
|
return ival;
|
|
}
|
|
|
|
Accumulator.prototype.peekDouble = function() {
|
|
this.assertReadableSize(8);
|
|
return isBigEndian ?
|
|
this.buf.readDoubleBE(this.readOffset) :
|
|
this.buf.readDoubleLE(this.readOffset);
|
|
}
|
|
|
|
Accumulator.prototype.readDouble = function() {
|
|
var dval = this.peekDouble();
|
|
this.readOffset += 8;
|
|
return dval;
|
|
}
|
|
|
|
Accumulator.prototype.readAdvance = function(size) {
|
|
if (size > 0) {
|
|
this.assertReadableSize(size);
|
|
} else if (size < 0 && this.readOffset + size < 0) {
|
|
throw new Error("advance with negative offset " + size +
|
|
" would seek off the start of the buffer");
|
|
}
|
|
this.readOffset += size;
|
|
}
|
|
|
|
Accumulator.prototype.writeByte = function(value) {
|
|
this.reserve(1);
|
|
this.buf.writeInt8(value, this.writeOffset);
|
|
++this.writeOffset;
|
|
}
|
|
|
|
Accumulator.prototype.writeInt = function(value, size) {
|
|
this.reserve(size);
|
|
switch (size) {
|
|
case 1:
|
|
this.buf.writeInt8(value, this.writeOffset);
|
|
break;
|
|
case 2:
|
|
if (isBigEndian) {
|
|
this.buf.writeInt16BE(value, this.writeOffset);
|
|
} else {
|
|
this.buf.writeInt16LE(value, this.writeOffset);
|
|
}
|
|
break;
|
|
case 4:
|
|
if (isBigEndian) {
|
|
this.buf.writeInt32BE(value, this.writeOffset);
|
|
} else {
|
|
this.buf.writeInt32LE(value, this.writeOffset);
|
|
}
|
|
break;
|
|
default:
|
|
throw new Error("unsupported integer size " + size);
|
|
}
|
|
this.writeOffset += size;
|
|
}
|
|
|
|
Accumulator.prototype.writeDouble = function(value) {
|
|
this.reserve(8);
|
|
if (isBigEndian) {
|
|
this.buf.writeDoubleBE(value, this.writeOffset);
|
|
} else {
|
|
this.buf.writeDoubleLE(value, this.writeOffset);
|
|
}
|
|
this.writeOffset += 8;
|
|
}
|
|
|
|
var BSER_ARRAY = 0x00;
|
|
var BSER_OBJECT = 0x01;
|
|
var BSER_STRING = 0x02;
|
|
var BSER_INT8 = 0x03;
|
|
var BSER_INT16 = 0x04;
|
|
var BSER_INT32 = 0x05;
|
|
var BSER_INT64 = 0x06;
|
|
var BSER_REAL = 0x07;
|
|
var BSER_TRUE = 0x08;
|
|
var BSER_FALSE = 0x09;
|
|
var BSER_NULL = 0x0a;
|
|
var BSER_TEMPLATE = 0x0b;
|
|
var BSER_SKIP = 0x0c;
|
|
|
|
var ST_NEED_PDU = 0; // Need to read and decode PDU length
|
|
var ST_FILL_PDU = 1; // Know the length, need to read whole content
|
|
|
|
var MAX_INT8 = 127;
|
|
var MAX_INT16 = 32767;
|
|
var MAX_INT32 = 2147483647;
|
|
|
|
function BunserBuf() {
|
|
EE.call(this);
|
|
this.buf = new Accumulator();
|
|
this.state = ST_NEED_PDU;
|
|
}
|
|
util.inherits(BunserBuf, EE);
|
|
exports.BunserBuf = BunserBuf;
|
|
|
|
BunserBuf.prototype.append = function(buf, synchronous) {
|
|
if (synchronous) {
|
|
this.buf.append(buf);
|
|
return this.process(synchronous);
|
|
}
|
|
|
|
try {
|
|
this.buf.append(buf);
|
|
} catch (err) {
|
|
this.emit('error', err);
|
|
return;
|
|
}
|
|
// Arrange to decode later. This allows the consuming
|
|
// application to make progress with other work in the
|
|
// case that we have a lot of subscription updates coming
|
|
// in from a large tree.
|
|
this.processLater();
|
|
}
|
|
|
|
BunserBuf.prototype.processLater = function() {
|
|
var self = this;
|
|
process.nextTick(function() {
|
|
try {
|
|
self.process(false);
|
|
} catch (err) {
|
|
self.emit('error', err);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Do something with the buffer to advance our state.
|
|
// If we're running synchronously we'll return either
|
|
// the value we've decoded or undefined if we don't
|
|
// yet have enought data.
|
|
// If we're running asynchronously, we'll emit the value
|
|
// when it becomes ready and schedule another invocation
|
|
// of process on the next tick if we still have data we
|
|
// can process.
|
|
BunserBuf.prototype.process = function(synchronous) {
|
|
if (this.state == ST_NEED_PDU) {
|
|
if (this.buf.readAvail() < 2) {
|
|
return;
|
|
}
|
|
// Validate BSER header
|
|
this.expectCode(0);
|
|
this.expectCode(1);
|
|
this.pduLen = this.decodeInt(true /* relaxed */);
|
|
if (this.pduLen === false) {
|
|
// Need more data, walk backwards
|
|
this.buf.readAdvance(-2);
|
|
return;
|
|
}
|
|
// Ensure that we have a big enough buffer to read the rest of the PDU
|
|
this.buf.reserve(this.pduLen);
|
|
this.state = ST_FILL_PDU;
|
|
}
|
|
|
|
if (this.state == ST_FILL_PDU) {
|
|
if (this.buf.readAvail() < this.pduLen) {
|
|
// Need more data
|
|
return;
|
|
}
|
|
|
|
// We have enough to decode it
|
|
var val = this.decodeAny();
|
|
if (synchronous) {
|
|
return val;
|
|
}
|
|
this.emit('value', val);
|
|
this.state = ST_NEED_PDU;
|
|
}
|
|
|
|
if (!synchronous && this.buf.readAvail() > 0) {
|
|
this.processLater();
|
|
}
|
|
}
|
|
|
|
BunserBuf.prototype.raise = function(reason) {
|
|
throw new Error(reason + ", in Buffer of length " +
|
|
this.buf.buf.length + " (" + this.buf.readAvail() +
|
|
" readable) at offset " + this.buf.readOffset + " buffer: " +
|
|
JSON.stringify(this.buf.buf.slice(
|
|
this.buf.readOffset, this.buf.readOffset + 32).toJSON()));
|
|
}
|
|
|
|
BunserBuf.prototype.expectCode = function(expected) {
|
|
var code = this.buf.readInt(1);
|
|
if (code != expected) {
|
|
this.raise("expected bser opcode " + expected + " but got " + code);
|
|
}
|
|
}
|
|
|
|
BunserBuf.prototype.decodeAny = function() {
|
|
var code = this.buf.peekInt(1);
|
|
switch (code) {
|
|
case BSER_INT8:
|
|
case BSER_INT16:
|
|
case BSER_INT32:
|
|
case BSER_INT64:
|
|
return this.decodeInt();
|
|
case BSER_REAL:
|
|
this.buf.readAdvance(1);
|
|
return this.buf.readDouble();
|
|
case BSER_TRUE:
|
|
this.buf.readAdvance(1);
|
|
return true;
|
|
case BSER_FALSE:
|
|
this.buf.readAdvance(1);
|
|
return false;
|
|
case BSER_NULL:
|
|
this.buf.readAdvance(1);
|
|
return null;
|
|
case BSER_STRING:
|
|
return this.decodeString();
|
|
case BSER_ARRAY:
|
|
return this.decodeArray();
|
|
case BSER_OBJECT:
|
|
return this.decodeObject();
|
|
case BSER_TEMPLATE:
|
|
return this.decodeTemplate();
|
|
default:
|
|
this.raise("unhandled bser opcode " + code);
|
|
}
|
|
}
|
|
|
|
BunserBuf.prototype.decodeArray = function() {
|
|
this.expectCode(BSER_ARRAY);
|
|
var nitems = this.decodeInt();
|
|
var arr = [];
|
|
for (var i = 0; i < nitems; ++i) {
|
|
arr.push(this.decodeAny());
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
BunserBuf.prototype.decodeObject = function() {
|
|
this.expectCode(BSER_OBJECT);
|
|
var nitems = this.decodeInt();
|
|
var res = {};
|
|
for (var i = 0; i < nitems; ++i) {
|
|
var key = this.decodeString();
|
|
var val = this.decodeAny();
|
|
res[key] = val;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
BunserBuf.prototype.decodeTemplate = function() {
|
|
this.expectCode(BSER_TEMPLATE);
|
|
var keys = this.decodeArray();
|
|
var nitems = this.decodeInt();
|
|
var arr = [];
|
|
for (var i = 0; i < nitems; ++i) {
|
|
var obj = {};
|
|
for (var keyidx = 0; keyidx < keys.length; ++keyidx) {
|
|
if (this.buf.peekInt(1) == BSER_SKIP) {
|
|
this.buf.readAdvance(1);
|
|
continue;
|
|
}
|
|
var val = this.decodeAny();
|
|
obj[keys[keyidx]] = val;
|
|
}
|
|
arr.push(obj);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
BunserBuf.prototype.decodeString = function() {
|
|
this.expectCode(BSER_STRING);
|
|
var len = this.decodeInt();
|
|
return this.buf.readString(len);
|
|
}
|
|
|
|
// This is unusual compared to the other decode functions in that
|
|
// we may not have enough data available to satisfy the read, and
|
|
// we don't want to throw. This is only true when we're reading
|
|
// the PDU length from the PDU header; we'll set relaxSizeAsserts
|
|
// in that case.
|
|
BunserBuf.prototype.decodeInt = function(relaxSizeAsserts) {
|
|
if (relaxSizeAsserts && !this.buf.readAvail(1)) {
|
|
return false;
|
|
} else {
|
|
this.buf.assertReadableSize(1);
|
|
}
|
|
var code = this.buf.peekInt(1);
|
|
var size = 0;
|
|
switch (code) {
|
|
case BSER_INT8:
|
|
size = 1;
|
|
break;
|
|
case BSER_INT16:
|
|
size = 2;
|
|
break;
|
|
case BSER_INT32:
|
|
size = 4;
|
|
break;
|
|
case BSER_INT64:
|
|
size = 8;
|
|
break;
|
|
default:
|
|
this.raise("invalid bser int encoding " + code);
|
|
}
|
|
|
|
if (relaxSizeAsserts && !this.buf.readAvail(1 + size)) {
|
|
return false;
|
|
}
|
|
this.buf.readAdvance(1);
|
|
return this.buf.readInt(size);
|
|
}
|
|
|
|
// synchronously BSER decode a string and return the value
|
|
function loadFromBuffer(input) {
|
|
var buf = new BunserBuf();
|
|
var result = buf.append(input, true);
|
|
if (buf.buf.readAvail()) {
|
|
throw Error(
|
|
'excess data found after input buffer, use BunserBuf instead');
|
|
}
|
|
if (typeof result === 'undefined') {
|
|
throw Error(
|
|
'no bser found in string and no error raised!?');
|
|
}
|
|
return result;
|
|
}
|
|
exports.loadFromBuffer = loadFromBuffer
|
|
|
|
// Byteswap an arbitrary buffer, flipping from one endian
|
|
// to the other, returning a new buffer with the resultant data
|
|
function byteswap64(buf) {
|
|
var swap = new Buffer(buf.length);
|
|
for (var i = 0; i < buf.length; i++) {
|
|
swap[i] = buf[buf.length -1 - i];
|
|
}
|
|
return swap;
|
|
}
|
|
|
|
function dump_int64(buf, val) {
|
|
// Get the raw bytes. The Int64 buffer is big endian
|
|
var be = val.toBuffer();
|
|
|
|
if (isBigEndian) {
|
|
// We're a big endian system, so the buffer is exactly how we
|
|
// want it to be
|
|
buf.writeByte(BSER_INT64);
|
|
buf.append(be);
|
|
return;
|
|
}
|
|
// We need to byte swap to get the correct representation
|
|
var le = byteswap64(be);
|
|
buf.writeByte(BSER_INT64);
|
|
buf.append(le);
|
|
}
|
|
|
|
function dump_int(buf, val) {
|
|
var abs = Math.abs(val);
|
|
if (abs <= MAX_INT8) {
|
|
buf.writeByte(BSER_INT8);
|
|
buf.writeInt(val, 1);
|
|
} else if (abs <= MAX_INT16) {
|
|
buf.writeByte(BSER_INT16);
|
|
buf.writeInt(val, 2);
|
|
} else if (abs <= MAX_INT32) {
|
|
buf.writeByte(BSER_INT32);
|
|
buf.writeInt(val, 4);
|
|
} else {
|
|
dump_int64(buf, new Int64(val));
|
|
}
|
|
}
|
|
|
|
function dump_any(buf, val) {
|
|
switch (typeof(val)) {
|
|
case 'number':
|
|
// check if it is an integer or a float
|
|
if (isFinite(val) && Math.floor(val) === val) {
|
|
dump_int(buf, val);
|
|
} else {
|
|
buf.writeByte(BSER_REAL);
|
|
buf.writeDouble(val);
|
|
}
|
|
return;
|
|
case 'string':
|
|
buf.writeByte(BSER_STRING);
|
|
dump_int(buf, Buffer.byteLength(val));
|
|
buf.append(val);
|
|
return;
|
|
case 'boolean':
|
|
buf.writeByte(val ? BSER_TRUE : BSER_FALSE);
|
|
return;
|
|
case 'object':
|
|
if (val === null) {
|
|
buf.writeByte(BSER_NULL);
|
|
return;
|
|
}
|
|
if (val instanceof Int64) {
|
|
dump_int64(buf, val);
|
|
return;
|
|
}
|
|
if (Array.isArray(val)) {
|
|
buf.writeByte(BSER_ARRAY);
|
|
dump_int(buf, val.length);
|
|
for (var i = 0; i < val.length; ++i) {
|
|
dump_any(buf, val[i]);
|
|
}
|
|
return;
|
|
}
|
|
buf.writeByte(BSER_OBJECT);
|
|
var keys = Object.keys(val);
|
|
|
|
// First pass to compute number of defined keys
|
|
var num_keys = keys.length;
|
|
for (var i = 0; i < keys.length; ++i) {
|
|
var key = keys[i];
|
|
var v = val[key];
|
|
if (typeof(v) == 'undefined') {
|
|
num_keys--;
|
|
}
|
|
}
|
|
dump_int(buf, num_keys);
|
|
for (var i = 0; i < keys.length; ++i) {
|
|
var key = keys[i];
|
|
var v = val[key];
|
|
if (typeof(v) == 'undefined') {
|
|
// Don't include it
|
|
continue;
|
|
}
|
|
dump_any(buf, key);
|
|
try {
|
|
dump_any(buf, v);
|
|
} catch (e) {
|
|
throw new Error(
|
|
e.message + ' (while serializing object property with name `' +
|
|
key + "')");
|
|
}
|
|
}
|
|
return;
|
|
|
|
default:
|
|
throw new Error('cannot serialize type ' + typeof(val) + ' to BSER');
|
|
}
|
|
}
|
|
|
|
// BSER encode value and return a buffer of the contents
|
|
function dumpToBuffer(val) {
|
|
var buf = new Accumulator();
|
|
// Build out the header
|
|
buf.writeByte(0);
|
|
buf.writeByte(1);
|
|
// Reserve room for an int32 to hold our PDU length
|
|
buf.writeByte(BSER_INT32);
|
|
buf.writeInt(0, 4); // We'll come back and fill this in at the end
|
|
|
|
dump_any(buf, val);
|
|
|
|
// Compute PDU length
|
|
var off = buf.writeOffset;
|
|
var len = off - 7 /* the header length */;
|
|
buf.writeOffset = 3; // The length value to fill in
|
|
buf.writeInt(len, 4); // write the length in the space we reserved
|
|
buf.writeOffset = off;
|
|
|
|
return buf.buf.slice(0, off);
|
|
}
|
|
exports.dumpToBuffer = dumpToBuffer
|
|
|
|
/***/ }),
|
|
/* 230 */
|
|
/***/ (function(module, exports) {
|
|
|
|
// Int64.js
|
|
//
|
|
// Copyright (c) 2012 Robert Kieffer
|
|
// MIT License - http://opensource.org/licenses/mit-license.php
|
|
|
|
/**
|
|
* Support for handling 64-bit int numbers in Javascript (node.js)
|
|
*
|
|
* JS Numbers are IEEE-754 binary double-precision floats, which limits the
|
|
* range of values that can be represented with integer precision to:
|
|
*
|
|
* 2^^53 <= N <= 2^53
|
|
*
|
|
* Int64 objects wrap a node Buffer that holds the 8-bytes of int64 data. These
|
|
* objects operate directly on the buffer which means that if they are created
|
|
* using an existing buffer then setting the value will modify the Buffer, and
|
|
* vice-versa.
|
|
*
|
|
* Internal Representation
|
|
*
|
|
* The internal buffer format is Big Endian. I.e. the most-significant byte is
|
|
* at buffer[0], the least-significant at buffer[7]. For the purposes of
|
|
* converting to/from JS native numbers, the value is assumed to be a signed
|
|
* integer stored in 2's complement form.
|
|
*
|
|
* For details about IEEE-754 see:
|
|
* http://en.wikipedia.org/wiki/Double_precision_floating-point_format
|
|
*/
|
|
|
|
// Useful masks and values for bit twiddling
|
|
var MASK31 = 0x7fffffff, VAL31 = 0x80000000;
|
|
var MASK32 = 0xffffffff, VAL32 = 0x100000000;
|
|
|
|
// Map for converting hex octets to strings
|
|
var _HEX = [];
|
|
for (var i = 0; i < 256; i++) {
|
|
_HEX[i] = (i > 0xF ? '' : '0') + i.toString(16);
|
|
}
|
|
|
|
//
|
|
// Int64
|
|
//
|
|
|
|
/**
|
|
* Constructor accepts any of the following argument types:
|
|
*
|
|
* new Int64(buffer[, offset=0]) - Existing Buffer with byte offset
|
|
* new Int64(Uint8Array[, offset=0]) - Existing Uint8Array with a byte offset
|
|
* new Int64(string) - Hex string (throws if n is outside int64 range)
|
|
* new Int64(number) - Number (throws if n is outside int64 range)
|
|
* new Int64(hi, lo) - Raw bits as two 32-bit values
|
|
*/
|
|
var Int64 = module.exports = function(a1, a2) {
|
|
if (a1 instanceof Buffer) {
|
|
this.buffer = a1;
|
|
this.offset = a2 || 0;
|
|
} else if (Object.prototype.toString.call(a1) == '[object Uint8Array]') {
|
|
// Under Browserify, Buffers can extend Uint8Arrays rather than an
|
|
// instance of Buffer. We could assume the passed in Uint8Array is actually
|
|
// a buffer but that won't handle the case where a raw Uint8Array is passed
|
|
// in. We construct a new Buffer just in case.
|
|
this.buffer = new Buffer(a1);
|
|
this.offset = a2 || 0;
|
|
} else {
|
|
this.buffer = this.buffer || new Buffer(8);
|
|
this.offset = 0;
|
|
this.setValue.apply(this, arguments);
|
|
}
|
|
};
|
|
|
|
|
|
// Max integer value that JS can accurately represent
|
|
Int64.MAX_INT = Math.pow(2, 53);
|
|
|
|
// Min integer value that JS can accurately represent
|
|
Int64.MIN_INT = -Math.pow(2, 53);
|
|
|
|
Int64.prototype = {
|
|
|
|
constructor: Int64,
|
|
|
|
/**
|
|
* Do in-place 2's compliment. See
|
|
* http://en.wikipedia.org/wiki/Two's_complement
|
|
*/
|
|
_2scomp: function() {
|
|
var b = this.buffer, o = this.offset, carry = 1;
|
|
for (var i = o + 7; i >= o; i--) {
|
|
var v = (b[i] ^ 0xff) + carry;
|
|
b[i] = v & 0xff;
|
|
carry = v >> 8;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Set the value. Takes any of the following arguments:
|
|
*
|
|
* setValue(string) - A hexidecimal string
|
|
* setValue(number) - Number (throws if n is outside int64 range)
|
|
* setValue(hi, lo) - Raw bits as two 32-bit values
|
|
*/
|
|
setValue: function(hi, lo) {
|
|
var negate = false;
|
|
if (arguments.length == 1) {
|
|
if (typeof(hi) == 'number') {
|
|
// Simplify bitfield retrieval by using abs() value. We restore sign
|
|
// later
|
|
negate = hi < 0;
|
|
hi = Math.abs(hi);
|
|
lo = hi % VAL32;
|
|
hi = hi / VAL32;
|
|
if (hi > VAL32) throw new RangeError(hi + ' is outside Int64 range');
|
|
hi = hi | 0;
|
|
} else if (typeof(hi) == 'string') {
|
|
hi = (hi + '').replace(/^0x/, '');
|
|
lo = hi.substr(-8);
|
|
hi = hi.length > 8 ? hi.substr(0, hi.length - 8) : '';
|
|
hi = parseInt(hi, 16);
|
|
lo = parseInt(lo, 16);
|
|
} else {
|
|
throw new Error(hi + ' must be a Number or String');
|
|
}
|
|
}
|
|
|
|
// Technically we should throw if hi or lo is outside int32 range here, but
|
|
// it's not worth the effort. Anything past the 32'nd bit is ignored.
|
|
|
|
// Copy bytes to buffer
|
|
var b = this.buffer, o = this.offset;
|
|
for (var i = 7; i >= 0; i--) {
|
|
b[o+i] = lo & 0xff;
|
|
lo = i == 4 ? hi : lo >>> 8;
|
|
}
|
|
|
|
// Restore sign of passed argument
|
|
if (negate) this._2scomp();
|
|
},
|
|
|
|
/**
|
|
* Convert to a native JS number.
|
|
*
|
|
* WARNING: Do not expect this value to be accurate to integer precision for
|
|
* large (positive or negative) numbers!
|
|
*
|
|
* @param allowImprecise If true, no check is performed to verify the
|
|
* returned value is accurate to integer precision. If false, imprecise
|
|
* numbers (very large positive or negative numbers) will be forced to +/-
|
|
* Infinity.
|
|
*/
|
|
toNumber: function(allowImprecise) {
|
|
var b = this.buffer, o = this.offset;
|
|
|
|
// Running sum of octets, doing a 2's complement
|
|
var negate = b[o] & 0x80, x = 0, carry = 1;
|
|
for (var i = 7, m = 1; i >= 0; i--, m *= 256) {
|
|
var v = b[o+i];
|
|
|
|
// 2's complement for negative numbers
|
|
if (negate) {
|
|
v = (v ^ 0xff) + carry;
|
|
carry = v >> 8;
|
|
v = v & 0xff;
|
|
}
|
|
|
|
x += v * m;
|
|
}
|
|
|
|
// Return Infinity if we've lost integer precision
|
|
if (!allowImprecise && x >= Int64.MAX_INT) {
|
|
return negate ? -Infinity : Infinity;
|
|
}
|
|
|
|
return negate ? -x : x;
|
|
},
|
|
|
|
/**
|
|
* Convert to a JS Number. Returns +/-Infinity for values that can't be
|
|
* represented to integer precision.
|
|
*/
|
|
valueOf: function() {
|
|
return this.toNumber(false);
|
|
},
|
|
|
|
/**
|
|
* Return string value
|
|
*
|
|
* @param radix Just like Number#toString()'s radix
|
|
*/
|
|
toString: function(radix) {
|
|
return this.valueOf().toString(radix || 10);
|
|
},
|
|
|
|
/**
|
|
* Return a string showing the buffer octets, with MSB on the left.
|
|
*
|
|
* @param sep separator string. default is '' (empty string)
|
|
*/
|
|
toOctetString: function(sep) {
|
|
var out = new Array(8);
|
|
var b = this.buffer, o = this.offset;
|
|
for (var i = 0; i < 8; i++) {
|
|
out[i] = _HEX[b[o+i]];
|
|
}
|
|
return out.join(sep || '');
|
|
},
|
|
|
|
/**
|
|
* Returns the int64's 8 bytes in a buffer.
|
|
*
|
|
* @param {bool} [rawBuffer=false] If no offset and this is true, return the internal buffer. Should only be used if
|
|
* you're discarding the Int64 afterwards, as it breaks encapsulation.
|
|
*/
|
|
toBuffer: function(rawBuffer) {
|
|
if (rawBuffer && this.offset === 0) return this.buffer;
|
|
|
|
var out = new Buffer(8);
|
|
this.buffer.copy(out, 0, this.offset, this.offset + 8);
|
|
return out;
|
|
},
|
|
|
|
/**
|
|
* Copy 8 bytes of int64 into target buffer at target offset.
|
|
*
|
|
* @param {Buffer} targetBuffer Buffer to copy into.
|
|
* @param {number} [targetOffset=0] Offset into target buffer.
|
|
*/
|
|
copy: function(targetBuffer, targetOffset) {
|
|
this.buffer.copy(targetBuffer, targetOffset || 0, this.offset, this.offset + 8);
|
|
},
|
|
|
|
/**
|
|
* Returns a number indicating whether this comes before or after or is the
|
|
* same as the other in sort order.
|
|
*
|
|
* @param {Int64} other Other Int64 to compare.
|
|
*/
|
|
compare: function(other) {
|
|
|
|
// If sign bits differ ...
|
|
if ((this.buffer[this.offset] & 0x80) != (other.buffer[other.offset] & 0x80)) {
|
|
return other.buffer[other.offset] - this.buffer[this.offset];
|
|
}
|
|
|
|
// otherwise, compare bytes lexicographically
|
|
for (var i = 0; i < 8; i++) {
|
|
if (this.buffer[this.offset+i] !== other.buffer[other.offset+i]) {
|
|
return this.buffer[this.offset+i] - other.buffer[other.offset+i];
|
|
}
|
|
}
|
|
return 0;
|
|
},
|
|
|
|
/**
|
|
* Returns a boolean indicating if this integer is equal to other.
|
|
*
|
|
* @param {Int64} other Other Int64 to compare.
|
|
*/
|
|
equals: function(other) {
|
|
return this.compare(other) === 0;
|
|
},
|
|
|
|
/**
|
|
* Pretty output in console.log
|
|
*/
|
|
inspect: function() {
|
|
return '[Int64 value:' + this + ' octets:' + this.toOctetString(' ') + ']';
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 231 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const events_1 = __webpack_require__(49);
|
|
const vscode_languageserver_types_1 = __webpack_require__(161);
|
|
const commands_1 = tslib_1.__importDefault(__webpack_require__(232));
|
|
const completion_1 = tslib_1.__importDefault(__webpack_require__(236));
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(316));
|
|
const extensions_1 = tslib_1.__importDefault(__webpack_require__(238));
|
|
const handler_1 = tslib_1.__importDefault(__webpack_require__(399));
|
|
const manager_2 = tslib_1.__importDefault(__webpack_require__(364));
|
|
const services_1 = tslib_1.__importDefault(__webpack_require__(351));
|
|
const manager_3 = tslib_1.__importDefault(__webpack_require__(233));
|
|
const sources_1 = tslib_1.__importDefault(__webpack_require__(237));
|
|
const types_1 = __webpack_require__(189);
|
|
const cursors_1 = tslib_1.__importDefault(__webpack_require__(407));
|
|
const clean_1 = tslib_1.__importDefault(__webpack_require__(409));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('plugin');
|
|
class Plugin extends events_1.EventEmitter {
|
|
constructor(nvim) {
|
|
super();
|
|
this.nvim = nvim;
|
|
this._ready = false;
|
|
Object.defineProperty(workspace_1.default, 'nvim', {
|
|
get: () => this.nvim
|
|
});
|
|
this.cursors = new cursors_1.default(nvim);
|
|
this.addMethod('hasProvider', async (id) => {
|
|
return this.handler.hasProvider(id);
|
|
});
|
|
this.addMethod('hasSelected', () => {
|
|
return completion_1.default.hasSelected();
|
|
});
|
|
this.addMethod('listNames', () => {
|
|
return manager_2.default.names;
|
|
});
|
|
this.addMethod('search', (...args) => {
|
|
return this.handler.search(args);
|
|
});
|
|
this.addMethod('cursorsSelect', (bufnr, kind, mode) => {
|
|
return this.cursors.select(bufnr, kind, mode);
|
|
});
|
|
this.addMethod('codeActionRange', (start, end, only) => {
|
|
return this.handler.codeActionRange(start, end, only);
|
|
});
|
|
this.addMethod('rootPatterns', bufnr => {
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return null;
|
|
return {
|
|
buffer: workspace_1.default.getRootPatterns(doc, types_1.PatternType.Buffer),
|
|
server: workspace_1.default.getRootPatterns(doc, types_1.PatternType.LanguageServer),
|
|
global: workspace_1.default.getRootPatterns(doc, types_1.PatternType.Global)
|
|
};
|
|
});
|
|
this.addMethod('installExtensions', async (...list) => {
|
|
await extensions_1.default.installExtensions(list);
|
|
});
|
|
this.addMethod('saveRefactor', async (bufnr) => {
|
|
await this.handler.saveRefactor(bufnr);
|
|
});
|
|
this.addMethod('updateExtensions', async () => {
|
|
await extensions_1.default.updateExtensions();
|
|
});
|
|
this.addMethod('commandList', () => {
|
|
return commands_1.default.commandList.map(o => o.id);
|
|
});
|
|
this.addMethod('openList', async (...args) => {
|
|
await this.ready;
|
|
await manager_2.default.start(args);
|
|
});
|
|
this.addMethod('runCommand', async (...args) => {
|
|
await this.ready;
|
|
return await this.handler.runCommand(...args);
|
|
});
|
|
this.addMethod('selectFunction', async (inner, visualmode) => {
|
|
return await this.handler.selectFunction(inner, visualmode);
|
|
});
|
|
this.addMethod('listResume', () => {
|
|
return manager_2.default.resume();
|
|
});
|
|
this.addMethod('listPrev', () => {
|
|
return manager_2.default.previous();
|
|
});
|
|
this.addMethod('listNext', () => {
|
|
return manager_2.default.next();
|
|
});
|
|
this.addMethod('detach', () => {
|
|
return workspace_1.default.detach();
|
|
});
|
|
this.addMethod('sendRequest', (id, method, params) => {
|
|
return services_1.default.sendRequest(id, method, params);
|
|
});
|
|
this.addMethod('registNotification', async (id, method) => {
|
|
await services_1.default.registNotification(id, method);
|
|
});
|
|
this.addMethod('doAutocmd', async (id, ...args) => {
|
|
let autocmd = workspace_1.default.autocmds.get(id);
|
|
if (autocmd) {
|
|
try {
|
|
await Promise.resolve(autocmd.callback.apply(autocmd.thisArg, args));
|
|
}
|
|
catch (e) {
|
|
logger.error(`Error on autocmd ${autocmd.event}`, e);
|
|
workspace_1.default.showMessage(`Error on autocmd ${autocmd.event}: ${e.message}`);
|
|
}
|
|
}
|
|
});
|
|
this.addMethod('updateConfig', (section, val) => {
|
|
workspace_1.default.configurations.updateUserConfig({ [section]: val });
|
|
});
|
|
this.addMethod('snippetNext', async () => {
|
|
await manager_3.default.nextPlaceholder();
|
|
return '';
|
|
});
|
|
this.addMethod('snippetPrev', async () => {
|
|
await manager_3.default.previousPlaceholder();
|
|
return '';
|
|
});
|
|
this.addMethod('snippetCancel', () => {
|
|
manager_3.default.cancel();
|
|
});
|
|
this.addMethod('openLog', () => {
|
|
let file = logger.getLogFile();
|
|
nvim.call(`coc#util#open_file`, ['edit', file], true);
|
|
});
|
|
this.addMethod('doKeymap', async (key, defaultReturn = '') => {
|
|
let [fn, repeat] = workspace_1.default.keymaps.get(key);
|
|
if (!fn) {
|
|
logger.error(`keymap for ${key} not found`);
|
|
return defaultReturn;
|
|
}
|
|
let res = await Promise.resolve(fn());
|
|
if (repeat)
|
|
await nvim.command(`silent! call repeat#set("\\<Plug>(coc-${key})", -1)`);
|
|
return res || defaultReturn;
|
|
});
|
|
this.addMethod('registExtensions', async (...folders) => {
|
|
for (let folder of folders) {
|
|
await extensions_1.default.loadExtension(folder);
|
|
}
|
|
});
|
|
workspace_1.default.onDidChangeWorkspaceFolders(() => {
|
|
nvim.setVar('WorkspaceFolders', workspace_1.default.folderPaths, true);
|
|
});
|
|
commands_1.default.init(nvim, this);
|
|
clean_1.default(); // tslint:disable-line
|
|
}
|
|
addMethod(name, fn) {
|
|
Object.defineProperty(this, name, { value: fn });
|
|
}
|
|
addCommand(cmd) {
|
|
let id = `vim.${cmd.id}`;
|
|
commands_1.default.registerCommand(id, async () => {
|
|
await this.nvim.command(cmd.cmd);
|
|
});
|
|
if (cmd.title)
|
|
commands_1.default.titles.set(id, cmd.title);
|
|
}
|
|
async init() {
|
|
let { nvim } = this;
|
|
try {
|
|
await extensions_1.default.init();
|
|
await workspace_1.default.init();
|
|
completion_1.default.init();
|
|
manager_1.default.init();
|
|
manager_2.default.init(nvim);
|
|
nvim.setVar('coc_workspace_initialized', 1, true);
|
|
nvim.setVar('coc_process_pid', process.pid, true);
|
|
nvim.setVar('WorkspaceFolders', workspace_1.default.folderPaths, true);
|
|
sources_1.default.init();
|
|
this.handler = new handler_1.default(nvim);
|
|
services_1.default.init();
|
|
await extensions_1.default.activateExtensions();
|
|
nvim.setVar('coc_service_initialized', 1, true);
|
|
nvim.call('coc#util#do_autocmd', ['CocNvimInit'], true);
|
|
this._ready = true;
|
|
let cmds = await nvim.getVar('coc_vim_commands');
|
|
if (cmds && cmds.length) {
|
|
for (let cmd of cmds) {
|
|
this.addCommand(cmd);
|
|
}
|
|
}
|
|
logger.info(`coc ${this.version} initialized with node: ${process.version}`);
|
|
this.emit('ready');
|
|
}
|
|
catch (e) {
|
|
this._ready = false;
|
|
console.error(`Error on initialize: ${e.stack}`); // tslint:disable-line
|
|
logger.error(e.stack);
|
|
}
|
|
workspace_1.default.onDidOpenTextDocument(async (doc) => {
|
|
if (!doc.uri.endsWith('coc-settings.json'))
|
|
return;
|
|
if (extensions_1.default.has('coc-json') || extensions_1.default.isDisabled('coc-json'))
|
|
return;
|
|
workspace_1.default.showMessage(`Run :CocInstall coc-json for json intellisense`, 'more');
|
|
});
|
|
}
|
|
get isReady() {
|
|
return this._ready;
|
|
}
|
|
get ready() {
|
|
if (this._ready)
|
|
return Promise.resolve();
|
|
return new Promise(resolve => {
|
|
this.once('ready', () => {
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
async findLocations(id, method, params, openCommand) {
|
|
let { document, position } = await workspace_1.default.getCurrentState();
|
|
params = params || {};
|
|
Object.assign(params, {
|
|
textDocument: { uri: document.uri },
|
|
position
|
|
});
|
|
let res = await services_1.default.sendRequest(id, method, params);
|
|
if (!res) {
|
|
workspace_1.default.showMessage(`Locations of "${method}" not found!`, 'warning');
|
|
return;
|
|
}
|
|
let locations = [];
|
|
if (Array.isArray(res)) {
|
|
locations = res;
|
|
}
|
|
else if (res.hasOwnProperty('location') && res.hasOwnProperty('children')) {
|
|
function getLocation(item) {
|
|
locations.push(item.location);
|
|
if (item.children && item.children.length) {
|
|
for (let loc of item.children) {
|
|
getLocation(loc);
|
|
}
|
|
}
|
|
}
|
|
getLocation(res);
|
|
}
|
|
await this.handler.handleLocations(locations, openCommand);
|
|
}
|
|
async snippetCheck(checkExpand, checkJump) {
|
|
if (checkExpand && !extensions_1.default.has('coc-snippets')) {
|
|
// tslint:disable-next-line: no-console
|
|
console.error('coc-snippets required for check expand status!');
|
|
return false;
|
|
}
|
|
if (checkJump) {
|
|
let jumpable = manager_3.default.jumpable();
|
|
if (jumpable)
|
|
return true;
|
|
}
|
|
if (checkExpand) {
|
|
let api = extensions_1.default.getExtensionApi('coc-snippets');
|
|
if (api && api.hasOwnProperty('expandable')) {
|
|
let expandable = await Promise.resolve(api.expandable());
|
|
if (expandable)
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
get version() {
|
|
return workspace_1.default.version + ( true ? '-' + "377c2729b9" : undefined);
|
|
}
|
|
async showInfo() {
|
|
if (!this.infoChannel) {
|
|
this.infoChannel = workspace_1.default.createOutputChannel('info');
|
|
}
|
|
else {
|
|
this.infoChannel.clear();
|
|
}
|
|
let channel = this.infoChannel;
|
|
channel.appendLine('## versions');
|
|
channel.appendLine('');
|
|
let out = await this.nvim.call('execute', ['version']);
|
|
channel.appendLine('vim version: ' + out.trim().split('\n', 2)[0]);
|
|
channel.appendLine('node version: ' + process.version);
|
|
channel.appendLine('coc.nvim version: ' + this.version);
|
|
channel.appendLine('term: ' + (process.env.TERM_PROGRAM || process.env.TERM));
|
|
channel.appendLine('platform: ' + process.platform);
|
|
channel.appendLine('');
|
|
channel.appendLine('## Messages');
|
|
let msgs = await this.nvim.call('coc#rpc#get_errors');
|
|
channel.append(msgs.join('\n'));
|
|
channel.appendLine('');
|
|
for (let ch of workspace_1.default.outputChannels.values()) {
|
|
if (ch.name !== 'info') {
|
|
channel.appendLine(`## Output channel: ${ch.name}\n`);
|
|
channel.append(ch.content);
|
|
channel.appendLine('');
|
|
}
|
|
}
|
|
channel.show();
|
|
}
|
|
async cocAction(...args) {
|
|
if (!this._ready)
|
|
return;
|
|
let { handler } = this;
|
|
try {
|
|
switch (args[0]) {
|
|
case 'links': {
|
|
return await handler.links();
|
|
}
|
|
case 'openLink': {
|
|
return await handler.openLink();
|
|
}
|
|
case 'pickColor': {
|
|
return await handler.pickColor();
|
|
}
|
|
case 'colorPresentation': {
|
|
return await handler.pickPresentation();
|
|
}
|
|
case 'highlight': {
|
|
await handler.highlight();
|
|
break;
|
|
}
|
|
case 'fold': {
|
|
return await handler.fold(args[1]);
|
|
}
|
|
case 'startCompletion':
|
|
await completion_1.default.startCompletion(args[1]);
|
|
break;
|
|
case 'sourceStat':
|
|
return sources_1.default.sourceStats();
|
|
case 'refreshSource':
|
|
await sources_1.default.refresh(args[1]);
|
|
break;
|
|
case 'toggleSource':
|
|
sources_1.default.toggleSource(args[1]);
|
|
break;
|
|
case 'diagnosticInfo':
|
|
await manager_1.default.echoMessage();
|
|
break;
|
|
case 'diagnosticNext':
|
|
await manager_1.default.jumpNext(args[1]);
|
|
break;
|
|
case 'diagnosticPrevious':
|
|
await manager_1.default.jumpPrevious(args[1]);
|
|
break;
|
|
case 'diagnosticList':
|
|
return manager_1.default.getDiagnosticList();
|
|
case 'jumpDefinition':
|
|
return await handler.gotoDefinition(args[1]);
|
|
case 'jumpDeclaration':
|
|
return await handler.gotoDeclaration(args[1]);
|
|
case 'jumpImplementation':
|
|
return await handler.gotoImplementation(args[1]);
|
|
case 'jumpTypeDefinition':
|
|
return await handler.gotoTypeDefinition(args[1]);
|
|
case 'jumpReferences':
|
|
return await handler.gotoReferences(args[1]);
|
|
case 'doHover':
|
|
return await handler.onHover();
|
|
case 'showSignatureHelp':
|
|
return await handler.showSignatureHelp();
|
|
case 'documentSymbols':
|
|
return await handler.getDocumentSymbols();
|
|
case 'symbolRanges':
|
|
return await handler.getSymbolsRanges();
|
|
case 'selectionRanges':
|
|
return await handler.getSelectionRanges();
|
|
case 'rangeSelect':
|
|
return await handler.selectRange(args[1], args[2]);
|
|
case 'rename':
|
|
await handler.rename(args[1]);
|
|
return;
|
|
case 'workspaceSymbols':
|
|
this.nvim.command('CocList -I symbols', true);
|
|
return;
|
|
case 'formatSelected':
|
|
return await handler.documentRangeFormatting(args[1]);
|
|
case 'format':
|
|
return await handler.documentFormatting();
|
|
case 'commands':
|
|
return await handler.getCommands();
|
|
case 'services':
|
|
return services_1.default.getServiceStats();
|
|
case 'toggleService':
|
|
return services_1.default.toggle(args[1]);
|
|
case 'codeAction':
|
|
return handler.doCodeAction(args[1], args[2]);
|
|
case 'doCodeAction':
|
|
return await handler.applyCodeAction(args[1]);
|
|
case 'codeActions':
|
|
return await handler.getCurrentCodeActions(args[1], args[2]);
|
|
case 'quickfixes':
|
|
return await handler.getCurrentCodeActions(args[1], [vscode_languageserver_types_1.CodeActionKind.QuickFix]);
|
|
case 'codeLensAction':
|
|
return handler.doCodeLensAction();
|
|
case 'runCommand':
|
|
return await handler.runCommand(...args.slice(1));
|
|
case 'doQuickfix':
|
|
return await handler.doQuickfix();
|
|
case 'refactor':
|
|
return await handler.doRefactor();
|
|
case 'repeatCommand':
|
|
return await commands_1.default.repeatCommand();
|
|
case 'extensionStats':
|
|
return await extensions_1.default.getExtensionStates();
|
|
case 'activeExtension':
|
|
return extensions_1.default.activate(args[1], false);
|
|
case 'deactivateExtension':
|
|
return extensions_1.default.deactivate(args[1]);
|
|
case 'reloadExtension':
|
|
return await extensions_1.default.reloadExtension(args[1]);
|
|
case 'toggleExtension':
|
|
return await extensions_1.default.toggleExtension(args[1]);
|
|
case 'uninstallExtension':
|
|
return await extensions_1.default.uninstallExtension(args.slice(1));
|
|
case 'getCurrentFunctionSymbol':
|
|
return await handler.getCurrentFunctionSymbol();
|
|
case 'getWordEdit':
|
|
return await handler.getWordEdit();
|
|
case 'addRanges':
|
|
return await this.cursors.addRanges(args[1]);
|
|
default:
|
|
workspace_1.default.showMessage(`unknown action ${args[0]}`, 'error');
|
|
}
|
|
}
|
|
catch (e) {
|
|
let message = e.hasOwnProperty('message') ? e.message : e.toString();
|
|
if (!/\btimeout\b/.test(message)) {
|
|
workspace_1.default.showMessage(`Error on '${args[0]}': ${message}`, 'error');
|
|
}
|
|
if (e.stack)
|
|
logger.error(e.stack);
|
|
}
|
|
}
|
|
async dispose() {
|
|
this.removeAllListeners();
|
|
manager_2.default.dispose();
|
|
workspace_1.default.dispose();
|
|
sources_1.default.dispose();
|
|
await services_1.default.stopAll();
|
|
services_1.default.dispose();
|
|
if (this.handler) {
|
|
this.handler.dispose();
|
|
}
|
|
manager_3.default.dispose();
|
|
commands_1.default.dispose();
|
|
completion_1.default.dispose();
|
|
manager_1.default.dispose();
|
|
}
|
|
}
|
|
exports.default = Plugin;
|
|
//# sourceMappingURL=plugin.js.map
|
|
|
|
/***/ }),
|
|
/* 232 */
|
|
/***/ (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__(149);
|
|
const util_1 = __webpack_require__(174);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(233));
|
|
const manager_2 = tslib_1.__importDefault(__webpack_require__(316));
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const logger = __webpack_require__(186)('commands');
|
|
class CommandItem {
|
|
constructor(id, impl, thisArg, internal = false) {
|
|
this.id = id;
|
|
this.impl = impl;
|
|
this.thisArg = thisArg;
|
|
this.internal = internal;
|
|
}
|
|
execute(...args) {
|
|
let { impl, thisArg } = this;
|
|
return impl.apply(thisArg, args || []);
|
|
}
|
|
dispose() {
|
|
this.thisArg = null;
|
|
this.impl = null;
|
|
}
|
|
}
|
|
class CommandManager {
|
|
constructor() {
|
|
this.commands = new Map();
|
|
this.titles = new Map();
|
|
}
|
|
init(nvim, plugin) {
|
|
this.mru = workspace_1.default.createMru('commands');
|
|
this.register({
|
|
id: 'vscode.open',
|
|
execute: async (url) => {
|
|
nvim.call('coc#util#open_url', url.toString(), true);
|
|
}
|
|
}, true);
|
|
this.register({
|
|
id: 'workbench.action.reloadWindow',
|
|
execute: () => {
|
|
nvim.command('CocRestart', true);
|
|
}
|
|
}, true);
|
|
this.register({
|
|
id: 'editor.action.insertSnippet',
|
|
execute: async (edit) => {
|
|
let doc = workspace_1.default.getDocument(workspace_1.default.bufnr);
|
|
if (!doc)
|
|
return;
|
|
await nvim.call('coc#_cancel', []);
|
|
if (doc.dirty)
|
|
doc.forceSync();
|
|
await manager_1.default.insertSnippet(edit.newText, true, edit.range);
|
|
}
|
|
}, true);
|
|
this.register({
|
|
id: 'editor.action.doCodeAction',
|
|
execute: async (action) => {
|
|
await plugin.cocAction('doCodeAction', action);
|
|
}
|
|
}, true);
|
|
this.register({
|
|
id: 'editor.action.triggerSuggest',
|
|
execute: async () => {
|
|
await util_1.wait(100);
|
|
nvim.call('coc#start', [], true);
|
|
}
|
|
}, true);
|
|
this.register({
|
|
id: 'editor.action.triggerParameterHints',
|
|
execute: async () => {
|
|
await util_1.wait(60);
|
|
await plugin.cocAction('showSignatureHelp');
|
|
}
|
|
}, true);
|
|
this.register({
|
|
id: 'editor.action.addRanges',
|
|
execute: async (ranges) => {
|
|
await plugin.cocAction('addRanges', ranges);
|
|
}
|
|
}, true);
|
|
this.register({
|
|
id: 'editor.action.restart',
|
|
execute: async () => {
|
|
await util_1.wait(30);
|
|
nvim.command('CocRestart', true);
|
|
}
|
|
}, true);
|
|
this.register({
|
|
id: 'editor.action.showReferences',
|
|
execute: async (_filepath, _position, references) => {
|
|
await workspace_1.default.showLocations(references);
|
|
}
|
|
}, true);
|
|
this.register({
|
|
id: 'editor.action.rename',
|
|
execute: async (uri, position) => {
|
|
await workspace_1.default.jumpTo(uri, position);
|
|
await plugin.cocAction('rename');
|
|
}
|
|
}, true);
|
|
this.register({
|
|
id: 'editor.action.format',
|
|
execute: async () => {
|
|
await plugin.cocAction('format');
|
|
}
|
|
}, true);
|
|
this.register({
|
|
id: 'workspace.diffDocument',
|
|
execute: async () => {
|
|
let document = await workspace_1.default.document;
|
|
if (!document)
|
|
return;
|
|
let lines = document.content.split('\n');
|
|
await nvim.call('coc#util#diff_content', [lines]);
|
|
}
|
|
}, true);
|
|
this.register({
|
|
id: 'workspace.clearWatchman',
|
|
execute: async () => {
|
|
await workspace_1.default.runCommand('watchman watch-del-all');
|
|
}
|
|
}, false, 'run watch-del-all for watchman to free up memory.');
|
|
this.register({
|
|
id: 'workspace.workspaceFolders',
|
|
execute: async () => {
|
|
let folders = workspace_1.default.workspaceFolders;
|
|
let lines = folders.map(folder => vscode_uri_1.URI.parse(folder.uri).fsPath);
|
|
await workspace_1.default.echoLines(lines);
|
|
}
|
|
}, false, 'show opened workspaceFolders.');
|
|
this.register({
|
|
id: 'workspace.renameCurrentFile',
|
|
execute: async () => {
|
|
await workspace_1.default.renameCurrent();
|
|
}
|
|
}, false, 'change current filename to a new name and reload it.');
|
|
this.register({
|
|
id: 'extensions.toggleAutoUpdate',
|
|
execute: async () => {
|
|
let config = workspace_1.default.getConfiguration('coc.preferences');
|
|
let interval = config.get('extensionUpdateCheck', 'daily');
|
|
if (interval == 'never') {
|
|
config.update('extensionUpdateCheck', 'daily', true);
|
|
workspace_1.default.showMessage('Extension auto update enabled.', 'more');
|
|
}
|
|
else {
|
|
config.update('extensionUpdateCheck', 'never', true);
|
|
workspace_1.default.showMessage('Extension auto update disabled.', 'more');
|
|
}
|
|
}
|
|
}, false, 'toggle auto update of extensions.');
|
|
this.register({
|
|
id: 'workspace.diagnosticRelated',
|
|
execute: () => {
|
|
return manager_2.default.jumpRelated();
|
|
}
|
|
}, false, 'jump to related locations of current diagnostic.');
|
|
this.register({
|
|
id: 'workspace.showOutput',
|
|
execute: async (name) => {
|
|
if (name) {
|
|
workspace_1.default.showOutputChannel(name);
|
|
}
|
|
else {
|
|
let names = workspace_1.default.channelNames;
|
|
if (names.length == 0)
|
|
return;
|
|
if (names.length == 1) {
|
|
workspace_1.default.showOutputChannel(names[0]);
|
|
}
|
|
else {
|
|
let idx = await workspace_1.default.showQuickpick(names);
|
|
if (idx == -1)
|
|
return;
|
|
let name = names[idx];
|
|
workspace_1.default.showOutputChannel(name);
|
|
}
|
|
}
|
|
}
|
|
}, false, 'open output buffer to show output from languageservers or extensions.');
|
|
this.register({
|
|
id: 'document.renameCurrentWord',
|
|
execute: async () => {
|
|
let bufnr = await nvim.call('bufnr', '%');
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return;
|
|
let edit = await plugin.cocAction('getWordEdit');
|
|
if (!edit) {
|
|
workspace_1.default.showMessage('Invalid position', 'warning');
|
|
return;
|
|
}
|
|
let ranges = [];
|
|
let { changes, documentChanges } = edit;
|
|
if (changes) {
|
|
let edits = changes[doc.uri];
|
|
if (edits)
|
|
ranges = edits.map(e => e.range);
|
|
}
|
|
else if (documentChanges) {
|
|
for (let c of documentChanges) {
|
|
if (vscode_languageserver_protocol_1.TextDocumentEdit.is(c) && c.textDocument.uri == doc.uri) {
|
|
ranges = c.edits.map(e => e.range);
|
|
}
|
|
}
|
|
}
|
|
if (ranges.length) {
|
|
await plugin.cocAction('addRanges', ranges);
|
|
}
|
|
}
|
|
}, false, 'rename word under cursor in current buffer by use multiple cursors.');
|
|
this.register({
|
|
id: 'document.jumpToNextSymbol',
|
|
execute: async () => {
|
|
let doc = await workspace_1.default.document;
|
|
if (!doc)
|
|
return;
|
|
let ranges = await plugin.cocAction('symbolRanges');
|
|
if (!ranges)
|
|
return;
|
|
let { textDocument } = doc;
|
|
let offset = await workspace_1.default.getOffset();
|
|
ranges.sort((a, b) => {
|
|
if (a.start.line != b.start.line) {
|
|
return a.start.line - b.start.line;
|
|
}
|
|
return a.start.character - b.start.character;
|
|
});
|
|
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;
|
|
}
|
|
}
|
|
await workspace_1.default.moveTo(ranges[0].start);
|
|
}
|
|
}, false, 'Jump to next symbol highlight position.');
|
|
}
|
|
get commandList() {
|
|
let res = [];
|
|
for (let item of this.commands.values()) {
|
|
if (!item.internal)
|
|
res.push(item);
|
|
}
|
|
return res;
|
|
}
|
|
dispose() {
|
|
for (const registration of this.commands.values()) {
|
|
registration.dispose();
|
|
}
|
|
this.commands.clear();
|
|
}
|
|
execute(command) {
|
|
let args = [command.command];
|
|
let arr = command.arguments;
|
|
if (arr)
|
|
args.push(...arr);
|
|
this.executeCommand.apply(this, args);
|
|
}
|
|
register(command, internal = false, description) {
|
|
for (const id of Array.isArray(command.id) ? command.id : [command.id]) {
|
|
this.registerCommand(id, command.execute, command, internal);
|
|
if (description)
|
|
this.titles.set(id, description);
|
|
}
|
|
return command;
|
|
}
|
|
has(id) {
|
|
return this.commands.has(id);
|
|
}
|
|
unregister(id) {
|
|
let item = this.commands.get(id);
|
|
if (!item)
|
|
return;
|
|
item.dispose();
|
|
this.commands.delete(id);
|
|
}
|
|
/**
|
|
* Registers a command that can be invoked via a keyboard shortcut,
|
|
* a menu item, an action, or directly.
|
|
*
|
|
* Registering a command with an existing command identifier twice
|
|
* will cause an error.
|
|
*
|
|
* @param command A unique identifier for the command.
|
|
* @param impl A command handler function.
|
|
* @param thisArg The `this` context used when invoking the handler function.
|
|
* @return Disposable which unregisters this command on disposal.
|
|
*/
|
|
registerCommand(id, impl, thisArg, internal = false) {
|
|
if (/^_/.test(id))
|
|
internal = true;
|
|
this.commands.set(id, new CommandItem(id, impl, thisArg, internal));
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.commands.delete(id);
|
|
});
|
|
}
|
|
/**
|
|
* Executes the command denoted by the given command identifier.
|
|
*
|
|
* * *Note 1:* When executing an editor command not all types are allowed to
|
|
* be passed as arguments. Allowed are the primitive types `string`, `boolean`,
|
|
* `number`, `undefined`, and `null`, as well as [`Position`](#Position), [`Range`](#Range), [`URI`](#URI) and [`Location`](#Location).
|
|
* * *Note 2:* There are no restrictions when executing commands that have been contributed
|
|
* by extensions.
|
|
*
|
|
* @param command Identifier of the command to execute.
|
|
* @param rest Parameters passed to the command function.
|
|
* @return A promise that resolves to the returned value of the given command. `undefined` when
|
|
* the command handler function doesn't return anything.
|
|
*/
|
|
executeCommand(command, ...rest) {
|
|
let cmd = this.commands.get(command);
|
|
if (!cmd) {
|
|
workspace_1.default.showMessage(`Command: ${command} not found`, 'error');
|
|
return;
|
|
}
|
|
return Promise.resolve(cmd.execute.apply(cmd, rest)).catch(e => {
|
|
workspace_1.default.showMessage(`Command error: ${e.message}`, 'error');
|
|
logger.error(e.stack);
|
|
});
|
|
}
|
|
async addRecent(cmd) {
|
|
await this.mru.add(cmd);
|
|
await workspace_1.default.nvim.command(`silent! call repeat#set("\\<Plug>(coc-command-repeat)", -1)`);
|
|
}
|
|
async repeatCommand() {
|
|
let mruList = await this.mru.load();
|
|
let first = mruList[0];
|
|
if (first) {
|
|
await this.executeCommand(first);
|
|
await workspace_1.default.nvim.command(`silent! call repeat#set("\\<Plug>(coc-command-repeat)", -1)`);
|
|
}
|
|
}
|
|
}
|
|
exports.CommandManager = CommandManager;
|
|
exports.default = new CommandManager();
|
|
//# sourceMappingURL=commands.js.map
|
|
|
|
/***/ }),
|
|
/* 233 */
|
|
/***/ (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__(148));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const Snippets = tslib_1.__importStar(__webpack_require__(234));
|
|
const parser_1 = __webpack_require__(234);
|
|
const session_1 = __webpack_require__(235);
|
|
const variableResolve_1 = __webpack_require__(398);
|
|
const logger = __webpack_require__(186)('snippets-manager');
|
|
class SnippetManager {
|
|
constructor() {
|
|
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();
|
|
}
|
|
});
|
|
}
|
|
let isActive = await session.start(snippet, select, range);
|
|
if (isActive) {
|
|
this.statusItem.show();
|
|
}
|
|
else if (session) {
|
|
session.deactivate();
|
|
}
|
|
nvim.command('silent! unlet g:coc_last_placeholder g:coc_selected_text', true);
|
|
return isActive;
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
exports.SnippetManager = SnippetManager;
|
|
exports.default = new SnippetManager();
|
|
//# sourceMappingURL=manager.js.map
|
|
|
|
/***/ }),
|
|
/* 234 */
|
|
/***/ (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__(149);
|
|
const logger = __webpack_require__(186)('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 };
|
|
}
|
|
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 };
|
|
}
|
|
// 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 };
|
|
}
|
|
// 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 };
|
|
}
|
|
// 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);
|
|
}
|
|
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);
|
|
}
|
|
})(others, parent);
|
|
}
|
|
get children() {
|
|
return this._children;
|
|
}
|
|
get snippet() {
|
|
let candidate = this;
|
|
while (true) {
|
|
if (!candidate) {
|
|
return undefined;
|
|
}
|
|
if (candidate instanceof TextmateSnippet) {
|
|
return candidate;
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
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();
|
|
}
|
|
if (this.children.length === 0 && !this.transform) {
|
|
return `\$${this.index}`;
|
|
}
|
|
else if (this.children.length === 0) {
|
|
return `\${${this.index}${transformString}}`;
|
|
}
|
|
else if (this.choice) {
|
|
return `\${${this.index}|${this.choice.toTextmateString()}|${transformString}}`;
|
|
}
|
|
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();
|
|
}
|
|
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);
|
|
}
|
|
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);
|
|
}
|
|
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([]);
|
|
}
|
|
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 {
|
|
ret += marker.toString();
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
else {
|
|
return value || '';
|
|
}
|
|
}
|
|
_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('');
|
|
}
|
|
toTextmateString() {
|
|
let value = '${';
|
|
value += this.index;
|
|
if (this.shorthandName) {
|
|
value += `:/${this.shorthandName}`;
|
|
}
|
|
else if (this.ifValue && this.elseValue) {
|
|
value += `:?${this.ifValue}:${this.elseValue}`;
|
|
}
|
|
else if (this.ifValue) {
|
|
value += `:+${this.ifValue}`;
|
|
}
|
|
else if (this.elseValue) {
|
|
value += `:-${this.elseValue}`;
|
|
}
|
|
value += '}';
|
|
return value;
|
|
}
|
|
clone() {
|
|
let ret = new FormatString(this.index, this.shorthandName, this.ifValue, this.elseValue);
|
|
return ret;
|
|
}
|
|
}
|
|
exports.FormatString = FormatString;
|
|
class Variable extends TransformableMarker {
|
|
constructor(name) {
|
|
super();
|
|
this.name = name;
|
|
}
|
|
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 newLines = value.split('\n').map((s, i) => {
|
|
return i == 0 ? s : ms[1] + s.replace(/^\s*/, '');
|
|
});
|
|
value = newLines.join('\n');
|
|
}
|
|
}
|
|
}
|
|
if (this.transform) {
|
|
value = this.transform.resolve(value || '');
|
|
}
|
|
if (value !== undefined) {
|
|
this._children = [new Text(value)];
|
|
return true;
|
|
}
|
|
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}}`;
|
|
}
|
|
}
|
|
clone() {
|
|
const ret = new Variable(this.name);
|
|
if (this.transform) {
|
|
ret.transform = this.transform.clone();
|
|
}
|
|
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 {
|
|
p.index = p.index + index;
|
|
}
|
|
}
|
|
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 {
|
|
p.appendChild(new Text(newText));
|
|
}
|
|
}
|
|
}
|
|
this._placeholders = undefined;
|
|
}
|
|
/**
|
|
* 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;
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
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(), '');
|
|
}
|
|
clone() {
|
|
let ret = new TextmateSnippet();
|
|
this._children = this.children.map(child => child.clone());
|
|
return ret;
|
|
}
|
|
walk(visitor) {
|
|
walk(this.children, visitor);
|
|
}
|
|
}
|
|
exports.TextmateSnippet = TextmateSnippet;
|
|
class SnippetParser {
|
|
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]);
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
_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;
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
_parse(marker) {
|
|
return this._parseEscaped(marker)
|
|
|| this._parseTabstopOrVariableName(marker)
|
|
|| this._parseComplexPlaceholder(marker)
|
|
|| this._parseComplexVariable(marker)
|
|
|| this._parseAnything(marker);
|
|
}
|
|
// \$, \\, \} -> 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:<children>}, ${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:<children>}
|
|
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;
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
else if (this._accept(6 /* Forwardslash */)) {
|
|
// ${1/<regex>/<format>/<options>}
|
|
if (this._parseTransform(placeholder)) {
|
|
parent.appendChild(placeholder);
|
|
return true;
|
|
}
|
|
this._backTo(token);
|
|
return false;
|
|
}
|
|
else if (this._accept(4 /* CurlyClose */)) {
|
|
// ${1}
|
|
parent.appendChild(placeholder);
|
|
return true;
|
|
}
|
|
else {
|
|
// ${1 <- missing curly or colon
|
|
return this._backTo(token);
|
|
}
|
|
}
|
|
_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);
|
|
}
|
|
if (values.length === 0) {
|
|
this._backTo(token);
|
|
return false;
|
|
}
|
|
parent.appendChild(new Text(values.join('')));
|
|
return true;
|
|
}
|
|
// ${foo:<children>}, ${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);
|
|
}
|
|
const variable = new Variable(name);
|
|
if (this._accept(1 /* Colon */)) {
|
|
// ${foo:<children>}
|
|
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 (this._accept(6 /* Forwardslash */)) {
|
|
// ${foo/<regex>/<format>/<options>}
|
|
if (this._parseTransform(variable)) {
|
|
parent.appendChild(variable);
|
|
return true;
|
|
}
|
|
this._backTo(token);
|
|
return false;
|
|
}
|
|
else if (this._accept(4 /* CurlyClose */)) {
|
|
// ${foo}
|
|
parent.appendChild(variable);
|
|
return true;
|
|
}
|
|
else {
|
|
// ${foo <- missing curly or colon
|
|
return this._backTo(token);
|
|
}
|
|
}
|
|
_parseTransform(parent) {
|
|
// ...<regex>/<format>/<options>}
|
|
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)) {
|
|
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;
|
|
}
|
|
try {
|
|
transform.regexp = new RegExp(regexValue, regexOptions);
|
|
}
|
|
catch (e) {
|
|
// invalid regexp
|
|
return false;
|
|
}
|
|
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;
|
|
}
|
|
else if (!complex) {
|
|
// $1
|
|
parent.appendChild(new FormatString(Number(index)));
|
|
return true;
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
else if (this._accept(11 /* Plus */)) {
|
|
// ${1:+<if>}
|
|
let ifValue = this._until(4 /* CurlyClose */);
|
|
if (ifValue) {
|
|
parent.appendChild(new FormatString(Number(index), undefined, ifValue, undefined));
|
|
return true;
|
|
}
|
|
}
|
|
else if (this._accept(12 /* Dash */)) {
|
|
// ${2:-<else>}
|
|
let elseValue = this._until(4 /* CurlyClose */);
|
|
if (elseValue) {
|
|
parent.appendChild(new FormatString(Number(index), undefined, undefined, elseValue));
|
|
return true;
|
|
}
|
|
}
|
|
else if (this._accept(13 /* QuestionMark */)) {
|
|
// ${2:?<if>:<else>}
|
|
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 {
|
|
// ${1:<else>}
|
|
let elseValue = this._until(4 /* CurlyClose */);
|
|
if (elseValue) {
|
|
parent.appendChild(new FormatString(Number(index), undefined, undefined, elseValue));
|
|
return true;
|
|
}
|
|
}
|
|
this._backTo(token);
|
|
return false;
|
|
}
|
|
_parseAnything(marker) {
|
|
if (this._token.type !== 14 /* EOF */) {
|
|
marker.appendChild(new Text(this._scanner.tokenText(this._token)));
|
|
this._accept(undefined);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
exports.SnippetParser = SnippetParser;
|
|
//# sourceMappingURL=parser.js.map
|
|
|
|
/***/ }),
|
|
/* 235 */
|
|
/***/ (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__(149);
|
|
const completion_1 = tslib_1.__importDefault(__webpack_require__(236));
|
|
const util_1 = __webpack_require__(174);
|
|
const position_1 = __webpack_require__(213);
|
|
const string_1 = __webpack_require__(210);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const snippet_1 = __webpack_require__(397);
|
|
const variableResolve_1 = __webpack_require__(398);
|
|
const logger = __webpack_require__(186)('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);
|
|
}
|
|
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;
|
|
}
|
|
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();
|
|
}
|
|
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;
|
|
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;
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
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() ? '' : '\\<C-n>';
|
|
await nvim.eval(`feedkeys("${pre}\\<C-y>", 'in')`);
|
|
return;
|
|
}
|
|
let resetVirtualEdit = false;
|
|
if (mode != 'n')
|
|
move_cmd += "\\<Esc>";
|
|
if (len == 0) {
|
|
if (col == 0 || (!mode.startsWith('i') && col < string_1.byteLength(line))) {
|
|
move_cmd += 'i';
|
|
}
|
|
else {
|
|
move_cmd += 'a';
|
|
}
|
|
}
|
|
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\\<c-g>`;
|
|
}
|
|
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}])`);
|
|
}
|
|
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;
|
|
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);
|
|
}
|
|
}
|
|
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
|
|
|
|
/***/ }),
|
|
/* 236 */
|
|
/***/ (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__(176));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const sources_1 = tslib_1.__importDefault(__webpack_require__(237));
|
|
const util_1 = __webpack_require__(174);
|
|
const string_1 = __webpack_require__(210);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const complete_1 = tslib_1.__importDefault(__webpack_require__(394));
|
|
const floating_1 = tslib_1.__importDefault(__webpack_require__(396));
|
|
const logger = __webpack_require__(186)('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;
|
|
}
|
|
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;
|
|
}
|
|
get option() {
|
|
if (!this.complete)
|
|
return null;
|
|
return this.complete.option;
|
|
}
|
|
addRecent(word, bufnr) {
|
|
if (!word)
|
|
return;
|
|
this.recentScores[`${bufnr}|${word}`] = Date.now();
|
|
}
|
|
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);
|
|
}
|
|
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;
|
|
}
|
|
get bufnr() {
|
|
let { option } = this;
|
|
return option ? option.bufnr : null;
|
|
}
|
|
get isActivated() {
|
|
return this.activated;
|
|
}
|
|
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', 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),
|
|
};
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
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);
|
|
}
|
|
hasSelected() {
|
|
if (workspace_1.default.env.pumevent)
|
|
return this.currItem != null;
|
|
if (this.config.noselect === false)
|
|
return true;
|
|
return this.isResolving;
|
|
}
|
|
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 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;
|
|
}
|
|
await this.resumeCompletion(content, search, true);
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
if (!hasInsert) {
|
|
// this could be wrong, but can't avoid.
|
|
this.isResolving = true;
|
|
return;
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
let content = await this.getPreviousContent(document);
|
|
if (content == null) {
|
|
// cursor line changed
|
|
this.stop();
|
|
return;
|
|
}
|
|
// check trigger character
|
|
if (sources_1.default.shouldTrigger(content, document.filetype)) {
|
|
await this.triggerCompletion(document, content, false);
|
|
return;
|
|
}
|
|
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;
|
|
}
|
|
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] = '';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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();
|
|
}
|
|
catch (e) {
|
|
// tslint:disable-next-line:no-console
|
|
console.error(e.stack);
|
|
logger.error(`error on complete done`, e.stack);
|
|
}
|
|
}
|
|
async onInsertLeave(bufnr) {
|
|
this.insertLeaveTs = Date.now();
|
|
if (this.isActivated) {
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (doc)
|
|
doc.forceSync();
|
|
this.stop();
|
|
}
|
|
}
|
|
async onInsertEnter(bufnr) {
|
|
if (!this.config.triggerAfterInsertEnter)
|
|
return;
|
|
let document = workspace_1.default.getDocument(bufnr);
|
|
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;
|
|
}
|
|
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')
|
|
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 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;
|
|
}
|
|
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 {
|
|
if (token.isCancellationRequested)
|
|
return;
|
|
await this.floating.show(docs, bounding, token);
|
|
}
|
|
this.resolveTokenSource = null;
|
|
}
|
|
start(complete) {
|
|
let { activated } = this;
|
|
this.activated = true;
|
|
this.isResolving = false;
|
|
if (activated) {
|
|
this.complete.dispose();
|
|
}
|
|
this.complete = complete;
|
|
if (!this.config.keepCompleteopt) {
|
|
this.nvim.command(`noa set completeopt=${this.completeOpt}`, true);
|
|
}
|
|
this.document.forceSync(true);
|
|
this.document.paused = true;
|
|
}
|
|
cancel() {
|
|
if (this.resolveTokenSource) {
|
|
this.resolveTokenSource.cancel();
|
|
this.resolveTokenSource = null;
|
|
}
|
|
}
|
|
stop() {
|
|
let { nvim } = this;
|
|
if (!this.activated)
|
|
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);
|
|
}
|
|
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
|
|
|
|
/***/ }),
|
|
/* 237 */
|
|
/***/ (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__(209));
|
|
const fs_1 = tslib_1.__importDefault(__webpack_require__(55));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const util_1 = tslib_1.__importDefault(__webpack_require__(40));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const extensions_1 = tslib_1.__importDefault(__webpack_require__(238));
|
|
const source_1 = tslib_1.__importDefault(__webpack_require__(389));
|
|
const source_vim_1 = tslib_1.__importDefault(__webpack_require__(390));
|
|
const types_1 = __webpack_require__(189);
|
|
const util_2 = __webpack_require__(174);
|
|
const fs_2 = __webpack_require__(200);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const string_1 = __webpack_require__(210);
|
|
const logger = __webpack_require__(186)('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__(391)).regist(this.sourceMap));
|
|
this.disposables.push((__webpack_require__(392)).regist(this.sourceMap));
|
|
this.disposables.push((__webpack_require__(393)).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 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)
|
|
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);
|
|
}
|
|
get names() {
|
|
return Array.from(this.sourceMap.keys());
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
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));
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
if (triggerPatterns && triggerPatterns.findIndex(p => p.test(pre)) !== -1) {
|
|
return true;
|
|
}
|
|
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;
|
|
}
|
|
return this.checkTrigger(source, pre, character);
|
|
});
|
|
}
|
|
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;
|
|
});
|
|
}
|
|
addSource(source) {
|
|
let { name } = source;
|
|
if (this.names.indexOf(name) !== -1) {
|
|
workspace_1.default.showMessage(`Source "${name}" recreated`, 'warning');
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
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();
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
onDocumentEnter(bufnr) {
|
|
let { sources } = this;
|
|
for (let s of sources) {
|
|
if (!s.enable)
|
|
continue;
|
|
if (typeof s.onEnter == 'function') {
|
|
s.onEnter(bufnr);
|
|
}
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
dispose() {
|
|
util_2.disposeAll(this.disposables);
|
|
}
|
|
}
|
|
exports.Sources = Sources;
|
|
exports.default = new Sources();
|
|
//# sourceMappingURL=sources.js.map
|
|
|
|
/***/ }),
|
|
/* 238 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const debounce_1 = __webpack_require__(176);
|
|
const fast_diff_1 = tslib_1.__importDefault(__webpack_require__(209));
|
|
const os_1 = tslib_1.__importDefault(__webpack_require__(56));
|
|
const fs_1 = tslib_1.__importDefault(__webpack_require__(55));
|
|
const isuri_1 = tslib_1.__importDefault(__webpack_require__(177));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const rimraf_1 = tslib_1.__importDefault(__webpack_require__(239));
|
|
const semver_1 = tslib_1.__importDefault(__webpack_require__(1));
|
|
const util_1 = __webpack_require__(40);
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const which_1 = tslib_1.__importDefault(__webpack_require__(181));
|
|
const commands_1 = tslib_1.__importDefault(__webpack_require__(232));
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const db_1 = tslib_1.__importDefault(__webpack_require__(206));
|
|
const extension_1 = tslib_1.__importDefault(__webpack_require__(251));
|
|
const memos_1 = tslib_1.__importDefault(__webpack_require__(308));
|
|
const util_2 = __webpack_require__(174);
|
|
const mkdirp_1 = tslib_1.__importDefault(__webpack_require__(179));
|
|
const array_1 = __webpack_require__(212);
|
|
__webpack_require__(309);
|
|
const factory_1 = __webpack_require__(310);
|
|
const fs_2 = __webpack_require__(200);
|
|
const watchman_1 = tslib_1.__importDefault(__webpack_require__(227));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const createLogger = __webpack_require__(186);
|
|
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)
|
|
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([]);
|
|
}
|
|
});
|
|
}
|
|
async activateExtensions() {
|
|
this.activated = true;
|
|
if (global.hasOwnProperty('__TEST__'))
|
|
return;
|
|
for (let item of this.list) {
|
|
let { id, packageJSON } = item.extension;
|
|
this.setupActiveEvents(id, packageJSON);
|
|
}
|
|
// check extensions need watch & install
|
|
this.checkExtensions().logError();
|
|
let config = workspace_1.default.getConfiguration('coc.preferences');
|
|
let interval = config.get('extensionUpdateCheck', 'daily');
|
|
if (interval != 'never') {
|
|
let now = new Date();
|
|
let day = new Date(now.getFullYear(), now.getMonth(), now.getDate() - (interval == 'daily' ? 0 : 7));
|
|
let ts = this.db.fetch('lastUpdate');
|
|
if (ts && Number(ts) > day.getTime())
|
|
return;
|
|
this.updateExtensions().logError();
|
|
}
|
|
}
|
|
async updateExtensions() {
|
|
if (!this.root)
|
|
await this.initializeRoot();
|
|
if (!this.npm)
|
|
return;
|
|
let lockedList = await this.getLockedList();
|
|
let stats = await this.globalExtensionStats();
|
|
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 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)
|
|
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)
|
|
return;
|
|
list = array_1.distinct(list);
|
|
let statusItem = workspace_1.default.createStatusBarItem(0, { progress: true });
|
|
statusItem.show();
|
|
statusItem.text = `Installing ${list.join(' ')}`;
|
|
await Promise.all(list.map(def => {
|
|
return this.manager.install(npm, def).then(name => {
|
|
if (name)
|
|
this.onExtensionInstall(name).logError();
|
|
}, err => {
|
|
workspace_1.default.showMessage(`Error on install ${def}: ${err}`);
|
|
});
|
|
}));
|
|
statusItem.dispose();
|
|
}
|
|
/**
|
|
* Get list of extensions in package.json that not installed
|
|
*/
|
|
getMissingExtensions() {
|
|
let json = this.loadJson() || { dependencies: {} };
|
|
let ids = [];
|
|
for (let key of Object.keys(json.dependencies)) {
|
|
let folder = path_1.default.join(this.root, 'node_modules', key);
|
|
if (!fs_1.default.existsSync(folder)) {
|
|
let val = json.dependencies[key];
|
|
if (val.startsWith('http')) {
|
|
ids.push(val);
|
|
}
|
|
else {
|
|
ids.push(key);
|
|
}
|
|
}
|
|
}
|
|
return ids;
|
|
}
|
|
get npm() {
|
|
let npm = workspace_1.default.getConfiguration('npm').get('binPath', 'npm');
|
|
if (npm.startsWith('~')) {
|
|
npm = os_1.default.homedir() + npm.slice(1);
|
|
}
|
|
for (let exe of [npm, 'yarnpkg', 'yarn', 'npm']) {
|
|
try {
|
|
let res = which_1.default.sync(exe);
|
|
return res;
|
|
}
|
|
catch (e) {
|
|
continue;
|
|
}
|
|
}
|
|
workspace_1.default.showMessage(`Can't find npm or yarn in your $PATH`, 'error');
|
|
return null;
|
|
}
|
|
/**
|
|
* Get all loaded extensions.
|
|
*/
|
|
get all() {
|
|
return this.list.map(o => o.extension);
|
|
}
|
|
getExtension(id) {
|
|
return this.list.find(o => o.id == id);
|
|
}
|
|
getExtensionState(id) {
|
|
let disabled = this.isDisabled(id);
|
|
if (disabled)
|
|
return 'disabled';
|
|
let item = this.list.find(o => o.id == id);
|
|
if (!item)
|
|
return 'unknown';
|
|
let { extension } = item;
|
|
return extension.isActive ? 'activated' : 'loaded';
|
|
}
|
|
async getExtensionStates() {
|
|
let globalStats = await this.globalExtensionStats();
|
|
let localStats = await this.localExtensionStats(globalStats);
|
|
return globalStats.concat(localStats);
|
|
}
|
|
async getLockedList() {
|
|
let obj = await this.db.fetch('extension');
|
|
obj = obj || {};
|
|
return Object.keys(obj).filter(id => {
|
|
return obj[id].locked === true;
|
|
});
|
|
}
|
|
async toggleLock(id) {
|
|
let key = `extension.${id}.locked`;
|
|
let locked = await this.db.fetch(key);
|
|
if (locked) {
|
|
this.db.delete(key);
|
|
}
|
|
else {
|
|
this.db.push(key, true);
|
|
}
|
|
}
|
|
async toggleExtension(id) {
|
|
let state = this.getExtensionState(id);
|
|
if (state == null)
|
|
return;
|
|
if (state == 'activated') {
|
|
this.deactivate(id);
|
|
}
|
|
let key = `extension.${id}.disabled`;
|
|
this.db.push(key, state == 'disabled' ? false : true);
|
|
if (state != 'disabled') {
|
|
this.disabled.add(id);
|
|
// unload
|
|
let idx = this.list.findIndex(o => o.id == id);
|
|
this.list.splice(idx, 1);
|
|
}
|
|
else {
|
|
this.disabled.delete(id);
|
|
let p = global.hasOwnProperty('__TEST__') ? '' : 'node_modules';
|
|
let folder = path_1.default.join(this.root, p, id);
|
|
try {
|
|
await this.loadExtension(folder);
|
|
}
|
|
catch (e) {
|
|
workspace_1.default.showMessage(`Can't load extension ${id}: ${e.message}'`, 'error');
|
|
}
|
|
}
|
|
await util_2.wait(200);
|
|
}
|
|
async reloadExtension(id) {
|
|
let idx = this.list.findIndex(o => o.id == id);
|
|
let directory = idx == -1 ? null : this.list[idx].directory;
|
|
this.deactivate(id);
|
|
if (idx != -1)
|
|
this.list.splice(idx, 1);
|
|
await util_2.wait(200);
|
|
if (directory) {
|
|
await this.loadExtension(directory);
|
|
}
|
|
else {
|
|
this.activate(id);
|
|
}
|
|
}
|
|
/**
|
|
* Remove all installed extensions
|
|
*/
|
|
async cleanExtensions() {
|
|
let dir = path_1.default.join(this.root, 'node_modules');
|
|
if (!fs_1.default.existsSync(dir))
|
|
return;
|
|
let names = fs_1.default.readdirSync(dir);
|
|
for (let name of names) {
|
|
let file = path_1.default.join(dir, name);
|
|
let stat = await util_1.promisify(fs_1.default.lstat)(file);
|
|
if (stat.isSymbolicLink())
|
|
continue;
|
|
await util_1.promisify(rimraf_1.default)(file, { glob: false });
|
|
}
|
|
}
|
|
async uninstallExtension(ids) {
|
|
if (!ids.length)
|
|
return;
|
|
let status = workspace_1.default.createStatusBarItem(99, { progress: true });
|
|
try {
|
|
status.text = `Uninstalling ${ids.join(' ')}`;
|
|
status.show();
|
|
let removed = [];
|
|
for (let id of ids) {
|
|
if (!this.isGlobalExtension(id)) {
|
|
workspace_1.default.showMessage(`Global extension '${id}' not found.`, 'error');
|
|
continue;
|
|
}
|
|
this.deactivate(id);
|
|
removed.push(id);
|
|
}
|
|
for (let id of removed) {
|
|
let idx = this.list.findIndex(o => o.id == id);
|
|
if (idx != -1) {
|
|
this.list.splice(idx, 1);
|
|
this._onDidUnloadExtension.fire(id);
|
|
}
|
|
}
|
|
let json = this.loadJson() || { dependencies: {} };
|
|
for (let id of removed) {
|
|
delete json.dependencies[id];
|
|
let folder = path_1.default.join(this.root, 'node_modules', id);
|
|
if (fs_1.default.existsSync(folder)) {
|
|
await util_1.promisify(rimraf_1.default)(`${folder}`, { glob: false });
|
|
}
|
|
}
|
|
let jsonFile = path_1.default.join(this.root, 'package.json');
|
|
status.dispose();
|
|
fs_1.default.writeFileSync(jsonFile, JSON.stringify(json, null, 2), { encoding: 'utf8' });
|
|
workspace_1.default.showMessage(`Removed: ${ids.join(' ')}`);
|
|
}
|
|
catch (e) {
|
|
status.dispose();
|
|
workspace_1.default.showMessage(`Uninstall failed: ${e.message}`, 'error');
|
|
}
|
|
}
|
|
isDisabled(id) {
|
|
return this.disabled.has(id);
|
|
}
|
|
async onExtensionInstall(id) {
|
|
if (!id)
|
|
return;
|
|
let item = this.list.find(o => o.id == id);
|
|
if (item)
|
|
item.deactivate();
|
|
let folder = path_1.default.join(this.root, 'node_modules', id);
|
|
let stat = await fs_2.statAsync(folder);
|
|
if (stat && stat.isDirectory()) {
|
|
let jsonFile = path_1.default.join(folder, 'package.json');
|
|
let content = await fs_2.readFile(jsonFile, 'utf8');
|
|
let packageJSON = JSON.parse(content);
|
|
let { engines } = packageJSON;
|
|
if (!engines || (!engines.hasOwnProperty('coc') && !engines.hasOwnProperty('vscode')))
|
|
return;
|
|
await this.loadExtension(folder);
|
|
}
|
|
}
|
|
has(id) {
|
|
return this.list.find(o => o.id == id) != null;
|
|
}
|
|
isActivated(id) {
|
|
let item = this.list.find(o => o.id == id);
|
|
if (item && item.extension.isActive) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
async loadExtension(folder, isLocal = false) {
|
|
let jsonFile = path_1.default.join(folder, 'package.json');
|
|
let stat = await fs_2.statAsync(jsonFile);
|
|
if (!stat || !stat.isFile())
|
|
return;
|
|
let content = await fs_2.readFile(jsonFile, 'utf8');
|
|
let packageJSON = JSON.parse(content);
|
|
if (this.isDisabled(packageJSON.name))
|
|
return;
|
|
if (this.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}`);
|
|
}
|
|
}
|
|
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));
|
|
}
|
|
}
|
|
/**
|
|
* Load single javascript file as extension.
|
|
*/
|
|
loadExtensionFile(filepath) {
|
|
let filename = path_1.default.basename(filepath);
|
|
let name = path_1.default.basename(filepath, 'js');
|
|
if (this.isDisabled(name))
|
|
return;
|
|
let root = path_1.default.dirname(filepath);
|
|
let packageJSON = {
|
|
name,
|
|
main: filename,
|
|
};
|
|
this.createExtension(root, packageJSON);
|
|
}
|
|
activate(id, silent = true) {
|
|
if (this.isDisabled(id)) {
|
|
if (!silent)
|
|
workspace_1.default.showMessage(`Extension ${id} is disabled!`, 'error');
|
|
return;
|
|
}
|
|
let item = this.list.find(o => o.id == id);
|
|
if (!item) {
|
|
workspace_1.default.showMessage(`Extension ${id} not found!`, 'error');
|
|
return;
|
|
}
|
|
let { extension } = item;
|
|
if (extension.isActive)
|
|
return;
|
|
extension.activate().then(() => {
|
|
if (extension.isActive) {
|
|
this._onDidActiveExtension.fire(extension);
|
|
}
|
|
}, e => {
|
|
workspace_1.default.showMessage(`Error on activate ${extension.id}: ${e.stack}`, 'error');
|
|
logger.error(`Error on activate extension ${extension.id}:`, e);
|
|
});
|
|
}
|
|
deactivate(id) {
|
|
let item = this.list.find(o => o.id == id);
|
|
if (!item)
|
|
return false;
|
|
if (item.extension.isActive && typeof item.deactivate == 'function') {
|
|
item.deactivate();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
async call(id, method, args) {
|
|
let item = this.list.find(o => o.id == id);
|
|
if (!item)
|
|
return workspace_1.default.showMessage(`extension ${id} not found`, 'error');
|
|
let { extension } = item;
|
|
if (!extension.isActive) {
|
|
workspace_1.default.showMessage(`extension ${id} not activated`, 'error');
|
|
return;
|
|
}
|
|
let { exports } = extension;
|
|
if (!exports || !exports.hasOwnProperty(method)) {
|
|
workspace_1.default.showMessage(`method ${method} not found on extension ${id}`, 'error');
|
|
return;
|
|
}
|
|
return await Promise.resolve(exports[method].apply(null, args));
|
|
}
|
|
getExtensionApi(id) {
|
|
let item = this.list.find(o => o.id == id);
|
|
if (!item)
|
|
return null;
|
|
let { extension } = item;
|
|
return extension.isActive ? extension.exports : null;
|
|
}
|
|
registerExtension(extension, deactivate) {
|
|
let { id, packageJSON } = extension;
|
|
this.list.push({ id, extension, deactivate, isLocal: true });
|
|
let { contributes } = packageJSON;
|
|
if (contributes) {
|
|
let { configuration } = contributes;
|
|
if (configuration && configuration.properties) {
|
|
let { properties } = configuration;
|
|
let props = {};
|
|
for (let key of Object.keys(properties)) {
|
|
let val = properties[key].default;
|
|
if (val != null)
|
|
props[key] = val;
|
|
}
|
|
workspace_1.default.configurations.extendsDefaults(props);
|
|
}
|
|
}
|
|
this._onDidLoadExtension.fire(extension);
|
|
this.setupActiveEvents(id, packageJSON);
|
|
}
|
|
get globalExtensions() {
|
|
let json = this.loadJson();
|
|
if (!json || !json.dependencies)
|
|
return [];
|
|
return Object.keys(json.dependencies);
|
|
}
|
|
async globalExtensionStats() {
|
|
let json = this.loadJson();
|
|
if (!json || !json.dependencies)
|
|
return [];
|
|
let res = await Promise.all(Object.keys(json.dependencies).map(key => {
|
|
return new Promise(async (resolve) => {
|
|
try {
|
|
let val = json.dependencies[key];
|
|
let root = path_1.default.join(this.root, 'node_modules', key);
|
|
let jsonFile = path_1.default.join(root, 'package.json');
|
|
let stat = await fs_2.statAsync(jsonFile);
|
|
if (!stat || !stat.isFile())
|
|
return resolve(null);
|
|
let content = await fs_2.readFile(jsonFile, 'utf8');
|
|
root = await fs_2.realpathAsync(root);
|
|
let obj = JSON.parse(content);
|
|
let { engines } = obj;
|
|
if (!engines || (!engines.hasOwnProperty('coc') && !engines.hasOwnProperty('vscode'))) {
|
|
return resolve(null);
|
|
}
|
|
let version = obj ? obj.version || '' : '';
|
|
let description = obj ? obj.description || '' : '';
|
|
let uri = isuri_1.default.isValid(val) ? val : null;
|
|
resolve({
|
|
id: key,
|
|
isLocal: false,
|
|
version,
|
|
description,
|
|
exotic: /^https?:/.test(val),
|
|
uri,
|
|
root,
|
|
state: this.getExtensionState(key)
|
|
});
|
|
}
|
|
catch (e) {
|
|
logger.error(e);
|
|
resolve(null);
|
|
}
|
|
});
|
|
}));
|
|
return res.filter(info => info != null);
|
|
}
|
|
async localExtensionStats(exclude) {
|
|
let runtimepath = await workspace_1.default.nvim.eval('&runtimepath');
|
|
let included = exclude.map(o => o.root);
|
|
let names = exclude.map(o => o.id);
|
|
let paths = runtimepath.split(',');
|
|
let res = await Promise.all(paths.map(root => {
|
|
return new Promise(async (resolve) => {
|
|
try {
|
|
if (included.includes(root)) {
|
|
return resolve(null);
|
|
}
|
|
let jsonFile = path_1.default.join(root, 'package.json');
|
|
let stat = await fs_2.statAsync(jsonFile);
|
|
if (!stat || !stat.isFile())
|
|
return resolve(null);
|
|
let content = await fs_2.readFile(jsonFile, 'utf8');
|
|
let obj = JSON.parse(content);
|
|
let { engines } = obj;
|
|
if (!engines || (!engines.hasOwnProperty('coc') && !engines.hasOwnProperty('vscode'))) {
|
|
return resolve(null);
|
|
}
|
|
if (names.indexOf(obj.name) !== -1) {
|
|
workspace_1.default.showMessage(`Skipped extension "${root}", please 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 = [];
|
|
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);
|
|
}
|
|
return id;
|
|
}
|
|
async initializeRoot() {
|
|
let root = this.root = await workspace_1.default.nvim.call('coc#util#extension_root');
|
|
if (!fs_1.default.existsSync(root)) {
|
|
mkdirp_1.default.sync(root);
|
|
}
|
|
let jsonFile = path_1.default.join(root, 'package.json');
|
|
if (!fs_1.default.existsSync(jsonFile)) {
|
|
fs_1.default.writeFileSync(jsonFile, '{"dependencies":{}}', 'utf8');
|
|
}
|
|
if (!this.db) {
|
|
let filepath = path_1.default.join(root, 'db.json');
|
|
this.db = new db_1.default(filepath);
|
|
}
|
|
this.manager = new extension_1.default(root);
|
|
}
|
|
}
|
|
exports.Extensions = Extensions;
|
|
exports.default = new Extensions();
|
|
//# sourceMappingURL=extensions.js.map
|
|
|
|
/***/ }),
|
|
/* 239 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const assert = __webpack_require__(101)
|
|
const path = __webpack_require__(57)
|
|
const fs = __webpack_require__(55)
|
|
let glob = undefined
|
|
try {
|
|
glob = __webpack_require__(240)
|
|
} catch (_err) {
|
|
// treat glob as optional.
|
|
}
|
|
|
|
const defaultGlobOpts = {
|
|
nosort: true,
|
|
silent: true
|
|
}
|
|
|
|
// for EMFILE handling
|
|
let timeout = 0
|
|
|
|
const isWindows = (process.platform === "win32")
|
|
|
|
const defaults = options => {
|
|
const methods = [
|
|
'unlink',
|
|
'chmod',
|
|
'stat',
|
|
'lstat',
|
|
'rmdir',
|
|
'readdir'
|
|
]
|
|
methods.forEach(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
|
|
if (options.glob === false) {
|
|
options.disableGlob = true
|
|
}
|
|
if (options.disableGlob !== true && glob === undefined) {
|
|
throw Error('glob dependency not found, set `options.disableGlob = true` if intentional')
|
|
}
|
|
options.disableGlob = options.disableGlob || false
|
|
options.glob = options.glob || defaultGlobOpts
|
|
}
|
|
|
|
const 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.equal(typeof cb, 'function', 'rimraf: callback function required')
|
|
assert(options, 'rimraf: invalid options argument provided')
|
|
assert.equal(typeof options, 'object', 'rimraf: options should be object')
|
|
|
|
defaults(options)
|
|
|
|
let busyTries = 0
|
|
let errState = null
|
|
let n = 0
|
|
|
|
const next = (er) => {
|
|
errState = errState || er
|
|
if (--n === 0)
|
|
cb(errState)
|
|
}
|
|
|
|
const afterGlob = (er, results) => {
|
|
if (er)
|
|
return cb(er)
|
|
|
|
n = results.length
|
|
if (n === 0)
|
|
return cb()
|
|
|
|
results.forEach(p => {
|
|
const CB = (er) => {
|
|
if (er) {
|
|
if ((er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") &&
|
|
busyTries < options.maxBusyTries) {
|
|
busyTries ++
|
|
// try again, with the same exact callback as this one.
|
|
return setTimeout(() => rimraf_(p, options, CB), busyTries * 100)
|
|
}
|
|
|
|
// this one won't happen if graceful-fs is used.
|
|
if (er.code === "EMFILE" && timeout < options.emfileWait) {
|
|
return setTimeout(() => rimraf_(p, options, CB), timeout ++)
|
|
}
|
|
|
|
// already gone
|
|
if (er.code === "ENOENT") er = null
|
|
}
|
|
|
|
timeout = 0
|
|
next(er)
|
|
}
|
|
rimraf_(p, options, CB)
|
|
})
|
|
}
|
|
|
|
if (options.disableGlob || !glob.hasMagic(p))
|
|
return afterGlob(null, [p])
|
|
|
|
options.lstat(p, (er, stat) => {
|
|
if (!er)
|
|
return afterGlob(null, [p])
|
|
|
|
glob(p, options.glob, afterGlob)
|
|
})
|
|
|
|
}
|
|
|
|
// 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.
|
|
const 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, (er, st) => {
|
|
if (er && er.code === "ENOENT")
|
|
return cb(null)
|
|
|
|
// Windows can EPERM on stat. Life is suffering.
|
|
if (er && er.code === "EPERM" && isWindows)
|
|
fixWinEPERM(p, options, er, cb)
|
|
|
|
if (st && st.isDirectory())
|
|
return rmdir(p, options, er, cb)
|
|
|
|
options.unlink(p, 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)
|
|
})
|
|
})
|
|
}
|
|
|
|
const fixWinEPERM = (p, options, er, cb) => {
|
|
assert(p)
|
|
assert(options)
|
|
assert(typeof cb === 'function')
|
|
if (er)
|
|
assert(er instanceof Error)
|
|
|
|
options.chmod(p, 0o666, er2 => {
|
|
if (er2)
|
|
cb(er2.code === "ENOENT" ? null : er)
|
|
else
|
|
options.stat(p, (er3, stats) => {
|
|
if (er3)
|
|
cb(er3.code === "ENOENT" ? null : er)
|
|
else if (stats.isDirectory())
|
|
rmdir(p, options, er, cb)
|
|
else
|
|
options.unlink(p, cb)
|
|
})
|
|
})
|
|
}
|
|
|
|
const fixWinEPERMSync = (p, options, er) => {
|
|
assert(p)
|
|
assert(options)
|
|
if (er)
|
|
assert(er instanceof Error)
|
|
|
|
try {
|
|
options.chmodSync(p, 0o666)
|
|
} catch (er2) {
|
|
if (er2.code === "ENOENT")
|
|
return
|
|
else
|
|
throw er
|
|
}
|
|
|
|
let stats
|
|
try {
|
|
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)
|
|
}
|
|
|
|
const 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, 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)
|
|
})
|
|
}
|
|
|
|
const rmkids = (p, options, cb) => {
|
|
assert(p)
|
|
assert(options)
|
|
assert(typeof cb === 'function')
|
|
|
|
options.readdir(p, (er, files) => {
|
|
if (er)
|
|
return cb(er)
|
|
let n = files.length
|
|
if (n === 0)
|
|
return options.rmdir(p, cb)
|
|
let errState
|
|
files.forEach(f => {
|
|
rimraf(path.join(p, f), options, 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.
|
|
const 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')
|
|
|
|
let results
|
|
|
|
if (options.disableGlob || !glob.hasMagic(p)) {
|
|
results = [p]
|
|
} else {
|
|
try {
|
|
options.lstatSync(p)
|
|
results = [p]
|
|
} catch (er) {
|
|
results = glob.sync(p, options.glob)
|
|
}
|
|
}
|
|
|
|
if (!results.length)
|
|
return
|
|
|
|
for (let i = 0; i < results.length; i++) {
|
|
const p = results[i]
|
|
|
|
let st
|
|
try {
|
|
st = options.lstatSync(p)
|
|
} catch (er) {
|
|
if (er.code === "ENOENT")
|
|
return
|
|
|
|
// Windows can EPERM on stat. Life is suffering.
|
|
if (er.code === "EPERM" && isWindows)
|
|
fixWinEPERMSync(p, options, er)
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
|
|
const 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)
|
|
}
|
|
}
|
|
|
|
const rmkidsSync = (p, options) => {
|
|
assert(p)
|
|
assert(options)
|
|
options.readdirSync(p).forEach(f => rimrafSync(path.join(p, f), options))
|
|
|
|
// We only end up here once we got ENOTEMPTY at least once, and
|
|
// at this point, we are guaranteed to have removed all the kids.
|
|
// So, we know that it won't be ENOENT or ENOTDIR or anything else.
|
|
// try really hard to delete stuff on windows, because it has a
|
|
// PROFOUNDLY annoying habit of not closing handles promptly when
|
|
// files are deleted, resulting in spurious ENOTEMPTY errors.
|
|
const retries = isWindows ? 100 : 1
|
|
let i = 0
|
|
do {
|
|
let threw = true
|
|
try {
|
|
const ret = options.rmdirSync(p, options)
|
|
threw = false
|
|
return ret
|
|
} finally {
|
|
if (++i < retries && threw)
|
|
continue
|
|
}
|
|
} while (true)
|
|
}
|
|
|
|
module.exports = rimraf
|
|
rimraf.sync = rimrafSync
|
|
|
|
|
|
/***/ }),
|
|
/* 240 */
|
|
/***/ (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__(55)
|
|
var rp = __webpack_require__(241)
|
|
var minimatch = __webpack_require__(201)
|
|
var Minimatch = minimatch.Minimatch
|
|
var inherits = __webpack_require__(243)
|
|
var EE = __webpack_require__(49).EventEmitter
|
|
var path = __webpack_require__(57)
|
|
var assert = __webpack_require__(101)
|
|
var isAbsolute = __webpack_require__(245)
|
|
var globSync = __webpack_require__(246)
|
|
var common = __webpack_require__(247)
|
|
var alphasort = common.alphasort
|
|
var alphasorti = common.alphasorti
|
|
var setopts = common.setopts
|
|
var ownProp = common.ownProp
|
|
var inflight = __webpack_require__(248)
|
|
var util = __webpack_require__(40)
|
|
var childrenIgnored = common.childrenIgnored
|
|
var isIgnored = common.isIgnored
|
|
|
|
var once = __webpack_require__(250)
|
|
|
|
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 (!pattern)
|
|
return false
|
|
|
|
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 {<filename>: 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
|
|
this._processing = 0
|
|
|
|
this._emitQueue = []
|
|
this._processQueue = []
|
|
this.paused = false
|
|
|
|
if (this.noprocess)
|
|
return this
|
|
|
|
if (n === 0)
|
|
return done()
|
|
|
|
var sync = true
|
|
for (var i = 0; i < n; i ++) {
|
|
this._process(this.minimatch.set[i], i, false, done)
|
|
}
|
|
sync = false
|
|
|
|
function done () {
|
|
--self._processing
|
|
if (self._processing <= 0) {
|
|
if (sync) {
|
|
process.nextTick(function () {
|
|
self._finish()
|
|
})
|
|
} else {
|
|
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)
|
|
rp.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])
|
|
}
|
|
}
|
|
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])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
//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)
|
|
}
|
|
// 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
|
|
}
|
|
this._process([e].concat(remain), index, inGlobStar, cb)
|
|
}
|
|
cb()
|
|
}
|
|
|
|
Glob.prototype._emitMatch = function (index, e) {
|
|
if (this.aborted)
|
|
return
|
|
|
|
if (isIgnored(this, e))
|
|
return
|
|
|
|
if (this.paused) {
|
|
this._emitQueue.push([index, e])
|
|
return
|
|
}
|
|
|
|
var abs = isAbsolute(e) ? e : this._makeAbs(e)
|
|
|
|
if (this.mark)
|
|
e = this._mark(e)
|
|
|
|
if (this.absolute)
|
|
e = abs
|
|
|
|
if (this.matches[index][e])
|
|
return
|
|
|
|
if (this.nodir) {
|
|
var c = this.cache[abs]
|
|
if (c === 'DIR' || Array.isArray(c))
|
|
return
|
|
}
|
|
|
|
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 && er.code === 'ENOENT')
|
|
return cb()
|
|
|
|
var isSym = lstat && 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 && !lstat.isDirectory()) {
|
|
self.cache[abs] = 'FILE'
|
|
cb()
|
|
} else
|
|
self._readdir(abs, false, cb)
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
var self = this
|
|
fs.readdir(abs, readdirCb(this, abs, cb))
|
|
}
|
|
|
|
function readdirCb (self, abs, cb) {
|
|
return function (er, entries) {
|
|
if (er)
|
|
self._readdirError(abs, er, cb)
|
|
else
|
|
self._readdirEntries(abs, entries, cb)
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
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.
|
|
var abs = this._makeAbs(f)
|
|
this.cache[abs] = 'FILE'
|
|
if (abs === this.cwdAbs) {
|
|
var error = new Error(er.code + ' invalid cwd ' + this.cwd)
|
|
error.path = this.cwd
|
|
error.code = er.code
|
|
this.emit('error', error)
|
|
this.abort()
|
|
}
|
|
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)
|
|
})
|
|
}
|
|
|
|
|
|
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
|
|
|
|
// 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)
|
|
}
|
|
|
|
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 (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.
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
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)
|
|
})
|
|
} else {
|
|
self._stat2(f, abs, er, lstat, cb)
|
|
}
|
|
}
|
|
}
|
|
|
|
Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
|
|
if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
|
|
this.statCache[abs] = false
|
|
return cb()
|
|
}
|
|
|
|
var needDir = f.slice(-1) === '/'
|
|
this.statCache[abs] = stat
|
|
|
|
if (abs.slice(-1) === '/' && stat && !stat.isDirectory())
|
|
return cb(null, false, stat)
|
|
|
|
var c = true
|
|
if (stat)
|
|
c = stat.isDirectory() ? 'DIR' : 'FILE'
|
|
this.cache[abs] = this.cache[abs] || c
|
|
|
|
if (needDir && c === 'FILE')
|
|
return cb()
|
|
|
|
return cb(null, c, stat)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 241 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
module.exports = realpath
|
|
realpath.realpath = realpath
|
|
realpath.sync = realpathSync
|
|
realpath.realpathSync = realpathSync
|
|
realpath.monkeypatch = monkeypatch
|
|
realpath.unmonkeypatch = unmonkeypatch
|
|
|
|
var fs = __webpack_require__(55)
|
|
var origRealpath = fs.realpath
|
|
var origRealpathSync = fs.realpathSync
|
|
|
|
var version = process.version
|
|
var ok = /^v[0-5]\./.test(version)
|
|
var old = __webpack_require__(242)
|
|
|
|
function newError (er) {
|
|
return er && er.syscall === 'realpath' && (
|
|
er.code === 'ELOOP' ||
|
|
er.code === 'ENOMEM' ||
|
|
er.code === 'ENAMETOOLONG'
|
|
)
|
|
}
|
|
|
|
function realpath (p, cache, cb) {
|
|
if (ok) {
|
|
return origRealpath(p, cache, cb)
|
|
}
|
|
|
|
if (typeof cache === 'function') {
|
|
cb = cache
|
|
cache = null
|
|
}
|
|
origRealpath(p, cache, function (er, result) {
|
|
if (newError(er)) {
|
|
old.realpath(p, cache, cb)
|
|
} else {
|
|
cb(er, result)
|
|
}
|
|
})
|
|
}
|
|
|
|
function realpathSync (p, cache) {
|
|
if (ok) {
|
|
return origRealpathSync(p, cache)
|
|
}
|
|
|
|
try {
|
|
return origRealpathSync(p, cache)
|
|
} catch (er) {
|
|
if (newError(er)) {
|
|
return old.realpathSync(p, cache)
|
|
} else {
|
|
throw er
|
|
}
|
|
}
|
|
}
|
|
|
|
function monkeypatch () {
|
|
fs.realpath = realpath
|
|
fs.realpathSync = realpathSync
|
|
}
|
|
|
|
function unmonkeypatch () {
|
|
fs.realpath = origRealpath
|
|
fs.realpathSync = origRealpathSync
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 242 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// 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.
|
|
|
|
var pathModule = __webpack_require__(57);
|
|
var isWindows = process.platform === 'win32';
|
|
var fs = __webpack_require__(55);
|
|
|
|
// JavaScript implementation of realpath, ported from node pre-v6
|
|
|
|
var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
|
|
|
|
function rethrow() {
|
|
// Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and
|
|
// is fairly slow to generate.
|
|
var callback;
|
|
if (DEBUG) {
|
|
var backtrace = new Error;
|
|
callback = debugCallback;
|
|
} else
|
|
callback = missingCallback;
|
|
|
|
return callback;
|
|
|
|
function debugCallback(err) {
|
|
if (err) {
|
|
backtrace.message = err.message;
|
|
err = backtrace;
|
|
missingCallback(err);
|
|
}
|
|
}
|
|
|
|
function missingCallback(err) {
|
|
if (err) {
|
|
if (process.throwDeprecation)
|
|
throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs
|
|
else if (!process.noDeprecation) {
|
|
var msg = 'fs: missing callback ' + (err.stack || err.message);
|
|
if (process.traceDeprecation)
|
|
console.trace(msg);
|
|
else
|
|
console.error(msg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function maybeCallback(cb) {
|
|
return typeof cb === 'function' ? cb : rethrow();
|
|
}
|
|
|
|
var normalize = pathModule.normalize;
|
|
|
|
// Regexp that finds the next partion of a (partial) path
|
|
// result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
|
|
if (isWindows) {
|
|
var nextPartRe = /(.*?)(?:[\/\\]+|$)/g;
|
|
} else {
|
|
var nextPartRe = /(.*?)(?:[\/]+|$)/g;
|
|
}
|
|
|
|
// Regex to find the device root, including trailing slash. E.g. 'c:\\'.
|
|
if (isWindows) {
|
|
var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/;
|
|
} else {
|
|
var splitRootRe = /^[\/]*/;
|
|
}
|
|
|
|
exports.realpathSync = function realpathSync(p, cache) {
|
|
// make p is absolute
|
|
p = pathModule.resolve(p);
|
|
|
|
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
|
|
return cache[p];
|
|
}
|
|
|
|
var original = p,
|
|
seenLinks = {},
|
|
knownHard = {};
|
|
|
|
// current character position in p
|
|
var pos;
|
|
// the partial path so far, including a trailing slash if any
|
|
var current;
|
|
// the partial path without a trailing slash (except when pointing at a root)
|
|
var base;
|
|
// the partial path scanned in the previous round, with slash
|
|
var previous;
|
|
|
|
start();
|
|
|
|
function start() {
|
|
// Skip over roots
|
|
var m = splitRootRe.exec(p);
|
|
pos = m[0].length;
|
|
current = m[0];
|
|
base = m[0];
|
|
previous = '';
|
|
|
|
// On windows, check that the root exists. On unix there is no need.
|
|
if (isWindows && !knownHard[base]) {
|
|
fs.lstatSync(base);
|
|
knownHard[base] = true;
|
|
}
|
|
}
|
|
|
|
// walk down the path, swapping out linked pathparts for their real
|
|
// values
|
|
// NB: p.length changes.
|
|
while (pos < p.length) {
|
|
// find the next part
|
|
nextPartRe.lastIndex = pos;
|
|
var result = nextPartRe.exec(p);
|
|
previous = current;
|
|
current += result[0];
|
|
base = previous + result[1];
|
|
pos = nextPartRe.lastIndex;
|
|
|
|
// continue if not a symlink
|
|
if (knownHard[base] || (cache && cache[base] === base)) {
|
|
continue;
|
|
}
|
|
|
|
var resolvedLink;
|
|
if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
|
|
// some known symbolic link. no need to stat again.
|
|
resolvedLink = cache[base];
|
|
} else {
|
|
var stat = fs.lstatSync(base);
|
|
if (!stat.isSymbolicLink()) {
|
|
knownHard[base] = true;
|
|
if (cache) cache[base] = base;
|
|
continue;
|
|
}
|
|
|
|
// read the link if it wasn't read before
|
|
// dev/ino always return 0 on windows, so skip the check.
|
|
var linkTarget = null;
|
|
if (!isWindows) {
|
|
var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
|
|
if (seenLinks.hasOwnProperty(id)) {
|
|
linkTarget = seenLinks[id];
|
|
}
|
|
}
|
|
if (linkTarget === null) {
|
|
fs.statSync(base);
|
|
linkTarget = fs.readlinkSync(base);
|
|
}
|
|
resolvedLink = pathModule.resolve(previous, linkTarget);
|
|
// track this, if given a cache.
|
|
if (cache) cache[base] = resolvedLink;
|
|
if (!isWindows) seenLinks[id] = linkTarget;
|
|
}
|
|
|
|
// resolve the link, then start over
|
|
p = pathModule.resolve(resolvedLink, p.slice(pos));
|
|
start();
|
|
}
|
|
|
|
if (cache) cache[original] = p;
|
|
|
|
return p;
|
|
};
|
|
|
|
|
|
exports.realpath = function realpath(p, cache, cb) {
|
|
if (typeof cb !== 'function') {
|
|
cb = maybeCallback(cache);
|
|
cache = null;
|
|
}
|
|
|
|
// make p is absolute
|
|
p = pathModule.resolve(p);
|
|
|
|
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
|
|
return process.nextTick(cb.bind(null, null, cache[p]));
|
|
}
|
|
|
|
var original = p,
|
|
seenLinks = {},
|
|
knownHard = {};
|
|
|
|
// current character position in p
|
|
var pos;
|
|
// the partial path so far, including a trailing slash if any
|
|
var current;
|
|
// the partial path without a trailing slash (except when pointing at a root)
|
|
var base;
|
|
// the partial path scanned in the previous round, with slash
|
|
var previous;
|
|
|
|
start();
|
|
|
|
function start() {
|
|
// Skip over roots
|
|
var m = splitRootRe.exec(p);
|
|
pos = m[0].length;
|
|
current = m[0];
|
|
base = m[0];
|
|
previous = '';
|
|
|
|
// On windows, check that the root exists. On unix there is no need.
|
|
if (isWindows && !knownHard[base]) {
|
|
fs.lstat(base, function(err) {
|
|
if (err) return cb(err);
|
|
knownHard[base] = true;
|
|
LOOP();
|
|
});
|
|
} else {
|
|
process.nextTick(LOOP);
|
|
}
|
|
}
|
|
|
|
// walk down the path, swapping out linked pathparts for their real
|
|
// values
|
|
function LOOP() {
|
|
// stop if scanned past end of path
|
|
if (pos >= p.length) {
|
|
if (cache) cache[original] = p;
|
|
return cb(null, p);
|
|
}
|
|
|
|
// find the next part
|
|
nextPartRe.lastIndex = pos;
|
|
var result = nextPartRe.exec(p);
|
|
previous = current;
|
|
current += result[0];
|
|
base = previous + result[1];
|
|
pos = nextPartRe.lastIndex;
|
|
|
|
// continue if not a symlink
|
|
if (knownHard[base] || (cache && cache[base] === base)) {
|
|
return process.nextTick(LOOP);
|
|
}
|
|
|
|
if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
|
|
// known symbolic link. no need to stat again.
|
|
return gotResolvedLink(cache[base]);
|
|
}
|
|
|
|
return fs.lstat(base, gotStat);
|
|
}
|
|
|
|
function gotStat(err, stat) {
|
|
if (err) return cb(err);
|
|
|
|
// if not a symlink, skip to the next path part
|
|
if (!stat.isSymbolicLink()) {
|
|
knownHard[base] = true;
|
|
if (cache) cache[base] = base;
|
|
return process.nextTick(LOOP);
|
|
}
|
|
|
|
// stat & read the link if not read before
|
|
// call gotTarget as soon as the link target is known
|
|
// dev/ino always return 0 on windows, so skip the check.
|
|
if (!isWindows) {
|
|
var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
|
|
if (seenLinks.hasOwnProperty(id)) {
|
|
return gotTarget(null, seenLinks[id], base);
|
|
}
|
|
}
|
|
fs.stat(base, function(err) {
|
|
if (err) return cb(err);
|
|
|
|
fs.readlink(base, function(err, target) {
|
|
if (!isWindows) seenLinks[id] = target;
|
|
gotTarget(err, target);
|
|
});
|
|
});
|
|
}
|
|
|
|
function gotTarget(err, target, base) {
|
|
if (err) return cb(err);
|
|
|
|
var resolvedLink = pathModule.resolve(previous, target);
|
|
if (cache) cache[base] = resolvedLink;
|
|
gotResolvedLink(resolvedLink);
|
|
}
|
|
|
|
function gotResolvedLink(resolvedLink) {
|
|
// resolve the link, then start over
|
|
p = pathModule.resolve(resolvedLink, p.slice(pos));
|
|
start();
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 243 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
try {
|
|
var util = __webpack_require__(40);
|
|
if (typeof util.inherits !== 'function') throw '';
|
|
module.exports = util.inherits;
|
|
} catch (e) {
|
|
module.exports = __webpack_require__(244);
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 244 */
|
|
/***/ (function(module, exports) {
|
|
|
|
if (typeof Object.create === 'function') {
|
|
// implementation from standard node.js 'util' module
|
|
module.exports = function inherits(ctor, superCtor) {
|
|
ctor.super_ = superCtor
|
|
ctor.prototype = Object.create(superCtor.prototype, {
|
|
constructor: {
|
|
value: ctor,
|
|
enumerable: false,
|
|
writable: true,
|
|
configurable: true
|
|
}
|
|
});
|
|
};
|
|
} else {
|
|
// old school shim for old browsers
|
|
module.exports = function inherits(ctor, superCtor) {
|
|
ctor.super_ = superCtor
|
|
var TempCtor = function () {}
|
|
TempCtor.prototype = superCtor.prototype
|
|
ctor.prototype = new TempCtor()
|
|
ctor.prototype.constructor = ctor
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 245 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
function posix(path) {
|
|
return path.charAt(0) === '/';
|
|
}
|
|
|
|
function win32(path) {
|
|
// https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56
|
|
var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/;
|
|
var result = splitDeviceRe.exec(path);
|
|
var device = result[1] || '';
|
|
var isUnc = Boolean(device && device.charAt(1) !== ':');
|
|
|
|
// UNC paths are always absolute
|
|
return Boolean(result[2] || isUnc);
|
|
}
|
|
|
|
module.exports = process.platform === 'win32' ? win32 : posix;
|
|
module.exports.posix = posix;
|
|
module.exports.win32 = win32;
|
|
|
|
|
|
/***/ }),
|
|
/* 246 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
module.exports = globSync
|
|
globSync.GlobSync = GlobSync
|
|
|
|
var fs = __webpack_require__(55)
|
|
var rp = __webpack_require__(241)
|
|
var minimatch = __webpack_require__(201)
|
|
var Minimatch = minimatch.Minimatch
|
|
var Glob = __webpack_require__(240).Glob
|
|
var util = __webpack_require__(40)
|
|
var path = __webpack_require__(57)
|
|
var assert = __webpack_require__(101)
|
|
var isAbsolute = __webpack_require__(245)
|
|
var common = __webpack_require__(247)
|
|
var alphasort = common.alphasort
|
|
var alphasorti = common.alphasorti
|
|
var setopts = common.setopts
|
|
var ownProp = common.ownProp
|
|
var childrenIgnored = common.childrenIgnored
|
|
var isIgnored = common.isIgnored
|
|
|
|
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')
|
|
|
|
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')
|
|
|
|
if (!(this instanceof GlobSync))
|
|
return new GlobSync(pattern, options)
|
|
|
|
setopts(this, pattern, options)
|
|
|
|
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()
|
|
}
|
|
|
|
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 = rp.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)
|
|
|
|
// 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)
|
|
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
|
|
|
|
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)
|
|
|
|
// if the abs isn't a dir, then nothing can match!
|
|
if (!entries)
|
|
return
|
|
|
|
// 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)
|
|
}
|
|
}
|
|
|
|
var len = matchedEntries.length
|
|
// If there are no matched entries, then nothing matches.
|
|
if (len === 0)
|
|
return
|
|
|
|
// 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.slice(-1) !== '/')
|
|
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
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
}
|
|
|
|
|
|
GlobSync.prototype._emitMatch = function (index, e) {
|
|
if (isIgnored(this, e))
|
|
return
|
|
|
|
var abs = this._makeAbs(e)
|
|
|
|
if (this.mark)
|
|
e = this._mark(e)
|
|
|
|
if (this.absolute) {
|
|
e = abs
|
|
}
|
|
|
|
if (this.matches[index][e])
|
|
return
|
|
|
|
if (this.nodir) {
|
|
var c = this.cache[abs]
|
|
if (c === 'DIR' || Array.isArray(c))
|
|
return
|
|
}
|
|
|
|
this.matches[index][e] = true
|
|
|
|
if (this.stat)
|
|
this._stat(e)
|
|
}
|
|
|
|
|
|
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 entries
|
|
var lstat
|
|
var stat
|
|
try {
|
|
lstat = fs.lstatSync(abs)
|
|
} catch (er) {
|
|
if (er.code === 'ENOENT') {
|
|
// lstat failed, doesn't exist
|
|
return null
|
|
}
|
|
}
|
|
|
|
var isSym = lstat && lstat.isSymbolicLink()
|
|
this.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 && !lstat.isDirectory())
|
|
this.cache[abs] = 'FILE'
|
|
else
|
|
entries = this._readdir(abs, false)
|
|
|
|
return entries
|
|
}
|
|
|
|
GlobSync.prototype._readdir = function (abs, inGlobStar) {
|
|
var entries
|
|
|
|
if (inGlobStar && !ownProp(this.symlinks, abs))
|
|
return this._readdirInGlobStar(abs)
|
|
|
|
if (ownProp(this.cache, abs)) {
|
|
var c = this.cache[abs]
|
|
if (!c || c === 'FILE')
|
|
return null
|
|
|
|
if (Array.isArray(c))
|
|
return c
|
|
}
|
|
|
|
try {
|
|
return this._readdirEntries(abs, fs.readdirSync(abs))
|
|
} catch (er) {
|
|
this._readdirError(abs, er)
|
|
return null
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
this.cache[abs] = entries
|
|
|
|
// mark and cache dir-ness
|
|
return entries
|
|
}
|
|
|
|
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.
|
|
var abs = this._makeAbs(f)
|
|
this.cache[abs] = 'FILE'
|
|
if (abs === this.cwdAbs) {
|
|
var error = new Error(er.code + ' invalid cwd ' + this.cwd)
|
|
error.path = this.cwd
|
|
error.code = er.code
|
|
throw error
|
|
}
|
|
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)
|
|
throw er
|
|
if (!this.silent)
|
|
console.error('glob error', er)
|
|
break
|
|
}
|
|
}
|
|
|
|
GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) {
|
|
|
|
var entries = this._readdir(abs, inGlobStar)
|
|
|
|
// no entries means not a dir, so it can never have matches
|
|
// foo.txt/** doesn't match foo.txt
|
|
if (!entries)
|
|
return
|
|
|
|
// 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)
|
|
}
|
|
}
|
|
|
|
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)
|
|
|
|
// If it doesn't exist, then just mark the lack of results
|
|
if (!exists)
|
|
return
|
|
|
|
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 (process.platform === 'win32')
|
|
prefix = prefix.replace(/\\/g, '/')
|
|
|
|
// Mark this as a match
|
|
this._emitMatch(index, prefix)
|
|
}
|
|
|
|
// Returns either 'DIR', 'FILE', or false
|
|
GlobSync.prototype._stat = function (f) {
|
|
var abs = this._makeAbs(f)
|
|
var needDir = f.slice(-1) === '/'
|
|
|
|
if (f.length > this.maxLength)
|
|
return false
|
|
|
|
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 c
|
|
|
|
if (needDir && c === 'FILE')
|
|
return false
|
|
|
|
// otherwise we have to stat, because maybe c=true
|
|
// if we know it exists, but not what it is.
|
|
}
|
|
|
|
var exists
|
|
var stat = this.statCache[abs]
|
|
if (!stat) {
|
|
var lstat
|
|
try {
|
|
lstat = fs.lstatSync(abs)
|
|
} catch (er) {
|
|
if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
|
|
this.statCache[abs] = false
|
|
return false
|
|
}
|
|
}
|
|
|
|
if (lstat && lstat.isSymbolicLink()) {
|
|
try {
|
|
stat = fs.statSync(abs)
|
|
} catch (er) {
|
|
stat = lstat
|
|
}
|
|
} else {
|
|
stat = lstat
|
|
}
|
|
}
|
|
|
|
this.statCache[abs] = stat
|
|
|
|
var c = true
|
|
if (stat)
|
|
c = stat.isDirectory() ? 'DIR' : 'FILE'
|
|
|
|
this.cache[abs] = this.cache[abs] || c
|
|
|
|
if (needDir && c === 'FILE')
|
|
return false
|
|
|
|
return c
|
|
}
|
|
|
|
GlobSync.prototype._mark = function (p) {
|
|
return common.mark(this, p)
|
|
}
|
|
|
|
GlobSync.prototype._makeAbs = function (f) {
|
|
return common.makeAbs(this, f)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 247 */
|
|
/***/ (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
|
|
|
|
function ownProp (obj, field) {
|
|
return Object.prototype.hasOwnProperty.call(obj, field)
|
|
}
|
|
|
|
var path = __webpack_require__(57)
|
|
var minimatch = __webpack_require__(201)
|
|
var isAbsolute = __webpack_require__(245)
|
|
var Minimatch = minimatch.Minimatch
|
|
|
|
function alphasorti (a, b) {
|
|
return a.toLowerCase().localeCompare(b.toLowerCase())
|
|
}
|
|
|
|
function alphasort (a, b) {
|
|
return a.localeCompare(b)
|
|
}
|
|
|
|
function setupIgnores (self, options) {
|
|
self.ignore = options.ignore || []
|
|
|
|
if (!Array.isArray(self.ignore))
|
|
self.ignore = [self.ignore]
|
|
|
|
if (self.ignore.length) {
|
|
self.ignore = self.ignore.map(ignoreMap)
|
|
}
|
|
}
|
|
|
|
// 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 })
|
|
}
|
|
|
|
return {
|
|
matcher: new Minimatch(pattern, { dot: true }),
|
|
gmatcher: gmatcher
|
|
}
|
|
}
|
|
|
|
function setopts (self, pattern, options) {
|
|
if (!options)
|
|
options = {}
|
|
|
|
// 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
|
|
}
|
|
|
|
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.absolute = !!options.absolute
|
|
|
|
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)
|
|
|
|
self.changedCwd = false
|
|
var cwd = process.cwd()
|
|
if (!ownProp(options, "cwd"))
|
|
self.cwd = cwd
|
|
else {
|
|
self.cwd = path.resolve(options.cwd)
|
|
self.changedCwd = self.cwd !== cwd
|
|
}
|
|
|
|
self.root = options.root || path.resolve(self.cwd, "/")
|
|
self.root = path.resolve(self.root)
|
|
if (process.platform === "win32")
|
|
self.root = self.root.replace(/\\/g, "/")
|
|
|
|
// TODO: is an absolute `cwd` supposed to be resolved against `root`?
|
|
// e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test')
|
|
self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd)
|
|
if (process.platform === "win32")
|
|
self.cwdAbs = self.cwdAbs.replace(/\\/g, "/")
|
|
self.nomount = !!options.nomount
|
|
|
|
// 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
|
|
}
|
|
|
|
function finish (self) {
|
|
var nou = self.nounique
|
|
var all = nou ? [] : Object.create(null)
|
|
|
|
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
|
|
})
|
|
}
|
|
}
|
|
|
|
if (!nou)
|
|
all = Object.keys(all)
|
|
|
|
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) {
|
|
var notDir = !(/\/$/.test(e))
|
|
var c = self.cache[e] || self.cache[makeAbs(self, e)]
|
|
if (notDir && c)
|
|
notDir = c !== 'DIR' && !Array.isArray(c)
|
|
return notDir
|
|
})
|
|
}
|
|
}
|
|
|
|
if (self.ignore.length)
|
|
all = all.filter(function(m) {
|
|
return !isIgnored(self, m)
|
|
})
|
|
|
|
self.found = all
|
|
}
|
|
|
|
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) === '/'
|
|
|
|
if (isDir && !slash)
|
|
m += '/'
|
|
else if (!isDir && slash)
|
|
m = m.slice(0, -1)
|
|
|
|
if (m !== p) {
|
|
var mabs = makeAbs(self, m)
|
|
self.statCache[mabs] = self.statCache[abs]
|
|
self.cache[mabs] = self.cache[abs]
|
|
}
|
|
}
|
|
|
|
return m
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
|
|
if (process.platform === 'win32')
|
|
abs = abs.replace(/\\/g, '/')
|
|
|
|
return abs
|
|
}
|
|
|
|
|
|
// 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
|
|
|
|
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
|
|
|
|
return self.ignore.some(function(item) {
|
|
return !!(item.gmatcher && item.gmatcher.match(path))
|
|
})
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 248 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var wrappy = __webpack_require__(249)
|
|
var reqs = Object.create(null)
|
|
var once = __webpack_require__(250)
|
|
|
|
module.exports = wrappy(inflight)
|
|
|
|
function inflight (key, cb) {
|
|
if (reqs[key]) {
|
|
reqs[key].push(cb)
|
|
return null
|
|
} else {
|
|
reqs[key] = [cb]
|
|
return makeres(key)
|
|
}
|
|
}
|
|
|
|
function makeres (key) {
|
|
return once(function RES () {
|
|
var cbs = reqs[key]
|
|
var len = cbs.length
|
|
var args = slice(arguments)
|
|
|
|
// XXX It's somewhat ambiguous whether a new callback added in this
|
|
// pass should be queued for later execution if something in the
|
|
// list of callbacks throws, or if it should just be discarded.
|
|
// However, it's such an edge case that it hardly matters, and either
|
|
// choice is likely as surprising as the other.
|
|
// As it happens, we do go ahead and schedule it for later execution.
|
|
try {
|
|
for (var i = 0; i < len; i++) {
|
|
cbs[i].apply(null, args)
|
|
}
|
|
} finally {
|
|
if (cbs.length > len) {
|
|
// added more in the interim.
|
|
// de-zalgo, just in case, but don't call again.
|
|
cbs.splice(0, len)
|
|
process.nextTick(function () {
|
|
RES.apply(null, args)
|
|
})
|
|
} else {
|
|
delete reqs[key]
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
function slice (args) {
|
|
var length = args.length
|
|
var array = []
|
|
|
|
for (var i = 0; i < length; i++) array[i] = args[i]
|
|
return array
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 249 */
|
|
/***/ (function(module, exports) {
|
|
|
|
// Returns a wrapper function that returns a wrapped callback
|
|
// The wrapper function should do some stuff, and return a
|
|
// presumably different callback function.
|
|
// This makes sure that own properties are retained, so that
|
|
// decorations and such are not lost along the way.
|
|
module.exports = wrappy
|
|
function wrappy (fn, cb) {
|
|
if (fn && cb) return wrappy(fn)(cb)
|
|
|
|
if (typeof fn !== 'function')
|
|
throw new TypeError('need wrapper function')
|
|
|
|
Object.keys(fn).forEach(function (k) {
|
|
wrapper[k] = fn[k]
|
|
})
|
|
|
|
return wrapper
|
|
|
|
function wrapper() {
|
|
var args = new Array(arguments.length)
|
|
for (var i = 0; i < args.length; i++) {
|
|
args[i] = arguments[i]
|
|
}
|
|
var ret = fn.apply(this, args)
|
|
var cb = args[args.length-1]
|
|
if (typeof ret === 'function' && ret !== cb) {
|
|
Object.keys(cb).forEach(function (k) {
|
|
ret[k] = cb[k]
|
|
})
|
|
}
|
|
return ret
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 250 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var wrappy = __webpack_require__(249)
|
|
module.exports = wrappy(once)
|
|
module.exports.strict = wrappy(onceStrict)
|
|
|
|
once.proto = once(function () {
|
|
Object.defineProperty(Function.prototype, 'once', {
|
|
value: function () {
|
|
return once(this)
|
|
},
|
|
configurable: true
|
|
})
|
|
|
|
Object.defineProperty(Function.prototype, 'onceStrict', {
|
|
value: function () {
|
|
return onceStrict(this)
|
|
},
|
|
configurable: true
|
|
})
|
|
})
|
|
|
|
function once (fn) {
|
|
var f = function () {
|
|
if (f.called) return f.value
|
|
f.called = true
|
|
return f.value = fn.apply(this, arguments)
|
|
}
|
|
f.called = false
|
|
return f
|
|
}
|
|
|
|
function onceStrict (fn) {
|
|
var f = function () {
|
|
if (f.called)
|
|
throw new Error(f.onceError)
|
|
f.called = true
|
|
return f.value = fn.apply(this, arguments)
|
|
}
|
|
var name = fn.name || 'Function wrapped with `once`'
|
|
f.onceError = name + " shouldn't be called more than once"
|
|
f.called = false
|
|
return f
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 251 */
|
|
/***/ (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__(175);
|
|
const fs_1 = tslib_1.__importDefault(__webpack_require__(55));
|
|
const mkdirp_1 = tslib_1.__importDefault(__webpack_require__(179));
|
|
const mv_1 = tslib_1.__importDefault(__webpack_require__(252));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const rc_1 = tslib_1.__importDefault(__webpack_require__(258));
|
|
const rimraf_1 = tslib_1.__importDefault(__webpack_require__(239));
|
|
const semver_1 = tslib_1.__importDefault(__webpack_require__(1));
|
|
const url_1 = tslib_1.__importDefault(__webpack_require__(264));
|
|
const util_1 = __webpack_require__(40);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const download_1 = tslib_1.__importDefault(__webpack_require__(265));
|
|
const fetch_1 = tslib_1.__importDefault(__webpack_require__(304));
|
|
const logger = __webpack_require__(186)('model-extension');
|
|
function registryUrl(scope = '') {
|
|
const result = rc_1.default('npm', { registry: 'https://registry.npmjs.org/' });
|
|
return result[`${scope}:registry`] || result.config_registry || result.registry;
|
|
}
|
|
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 filepath = path_1.default.join(this.root, 'node_modules/.cache', `${info.name}-`);
|
|
if (!fs_1.default.existsSync(path_1.default.dirname(filepath))) {
|
|
fs_1.default.mkdirSync(path_1.default.dirname(filepath));
|
|
}
|
|
let tmpFolder = await util_1.promisify(fs_1.default.mkdtemp)(filepath);
|
|
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'];
|
|
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;
|
|
}
|
|
fs_1.default.writeFileSync(jsonFile, JSON.stringify(obj, 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
|
|
};
|
|
}
|
|
}
|
|
exports.default = ExtensionManager;
|
|
//# sourceMappingURL=extension.js.map
|
|
|
|
/***/ }),
|
|
/* 252 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var fs = __webpack_require__(55);
|
|
var ncp = __webpack_require__(253).ncp;
|
|
var path = __webpack_require__(57);
|
|
var rimraf = __webpack_require__(254);
|
|
var mkdirp = __webpack_require__(179);
|
|
|
|
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);
|
|
return;
|
|
}
|
|
if (err.code === 'EISDIR' || err.code === 'EPERM') {
|
|
moveDirAcrossDevice(source, dest, clobber, limit, cb);
|
|
return;
|
|
}
|
|
cb(err);
|
|
return;
|
|
}
|
|
fs.unlink(source, 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 {
|
|
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);
|
|
}
|
|
}
|
|
|
|
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);
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 253 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var fs = __webpack_require__(55),
|
|
path = __webpack_require__(57);
|
|
|
|
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);
|
|
}
|
|
}
|
|
else if (typeof filter === 'function') {
|
|
if (!filter(source)) {
|
|
return cb(true);
|
|
}
|
|
}
|
|
}
|
|
return getStats(source);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
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();
|
|
}
|
|
});
|
|
}
|
|
|
|
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();
|
|
});
|
|
}
|
|
|
|
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);
|
|
}
|
|
if (dereference) {
|
|
targetDest = path.resolve(basePath, targetDest);
|
|
}
|
|
if (targetDest === resolvedPath) {
|
|
return cb();
|
|
}
|
|
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 if (!errs) {
|
|
errs = [];
|
|
}
|
|
if (typeof errs.write === 'undefined') {
|
|
errs.push(err);
|
|
}
|
|
else {
|
|
errs.write(err.stack + '\n\n');
|
|
}
|
|
return cb();
|
|
}
|
|
|
|
function cb(skipped) {
|
|
if (!skipped) running--;
|
|
finished++;
|
|
if ((started === finished) && (running === 0)) {
|
|
if (cback !== undefined ) {
|
|
return errs ? cback(errs) : cback(null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/***/ }),
|
|
/* 254 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
module.exports = rimraf
|
|
rimraf.sync = rimrafSync
|
|
|
|
var assert = __webpack_require__(101)
|
|
var path = __webpack_require__(57)
|
|
var fs = __webpack_require__(55)
|
|
var glob = __webpack_require__(255)
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 255 */
|
|
/***/ (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__(55)
|
|
var minimatch = __webpack_require__(201)
|
|
var Minimatch = minimatch.Minimatch
|
|
var inherits = __webpack_require__(243)
|
|
var EE = __webpack_require__(49).EventEmitter
|
|
var path = __webpack_require__(57)
|
|
var assert = __webpack_require__(101)
|
|
var isAbsolute = __webpack_require__(245)
|
|
var globSync = __webpack_require__(256)
|
|
var common = __webpack_require__(257)
|
|
var alphasort = common.alphasort
|
|
var alphasorti = common.alphasorti
|
|
var setopts = common.setopts
|
|
var ownProp = common.ownProp
|
|
var inflight = __webpack_require__(248)
|
|
var util = __webpack_require__(40)
|
|
var childrenIgnored = common.childrenIgnored
|
|
var isIgnored = common.isIgnored
|
|
|
|
var once = __webpack_require__(250)
|
|
|
|
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 {<filename>: 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])
|
|
}
|
|
}
|
|
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])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
//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)
|
|
}
|
|
// 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
|
|
}
|
|
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)
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
var self = this
|
|
fs.readdir(abs, readdirCb(this, abs, cb))
|
|
}
|
|
|
|
function readdirCb (self, abs, cb) {
|
|
return function (er, entries) {
|
|
if (er)
|
|
self._readdirError(abs, er, cb)
|
|
else
|
|
self._readdirEntries(abs, entries, cb)
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
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)
|
|
})
|
|
}
|
|
|
|
|
|
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
|
|
|
|
// 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)
|
|
}
|
|
|
|
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 (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.
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
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)
|
|
})
|
|
} 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()
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 256 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
module.exports = globSync
|
|
globSync.GlobSync = GlobSync
|
|
|
|
var fs = __webpack_require__(55)
|
|
var minimatch = __webpack_require__(201)
|
|
var Minimatch = minimatch.Minimatch
|
|
var Glob = __webpack_require__(255).Glob
|
|
var util = __webpack_require__(40)
|
|
var path = __webpack_require__(57)
|
|
var assert = __webpack_require__(101)
|
|
var isAbsolute = __webpack_require__(245)
|
|
var common = __webpack_require__(257)
|
|
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')
|
|
|
|
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')
|
|
|
|
if (!(this instanceof GlobSync))
|
|
return new GlobSync(pattern, options)
|
|
|
|
setopts(this, pattern, options)
|
|
|
|
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()
|
|
}
|
|
|
|
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)
|
|
|
|
// 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)
|
|
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
|
|
|
|
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)
|
|
|
|
// if the abs isn't a dir, then nothing can match!
|
|
if (!entries)
|
|
return
|
|
|
|
// 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)
|
|
}
|
|
}
|
|
|
|
var len = matchedEntries.length
|
|
// If there are no matched entries, then nothing matches.
|
|
if (len === 0)
|
|
return
|
|
|
|
// 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.slice(-1) !== '/')
|
|
e = prefix + '/' + e
|
|
else
|
|
e = prefix + e
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
}
|
|
|
|
|
|
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
|
|
}
|
|
|
|
this.matches[index][e] = true
|
|
if (this.stat)
|
|
this._stat(e)
|
|
}
|
|
|
|
|
|
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 entries
|
|
var lstat
|
|
var stat
|
|
try {
|
|
lstat = fs.lstatSync(abs)
|
|
} catch (er) {
|
|
// lstat failed, doesn't exist
|
|
return null
|
|
}
|
|
|
|
var isSym = lstat.isSymbolicLink()
|
|
this.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())
|
|
this.cache[abs] = 'FILE'
|
|
else
|
|
entries = this._readdir(abs, false)
|
|
|
|
return entries
|
|
}
|
|
|
|
GlobSync.prototype._readdir = function (abs, inGlobStar) {
|
|
var entries
|
|
|
|
if (inGlobStar && !ownProp(this.symlinks, abs))
|
|
return this._readdirInGlobStar(abs)
|
|
|
|
if (ownProp(this.cache, abs)) {
|
|
var c = this.cache[abs]
|
|
if (!c || c === 'FILE')
|
|
return null
|
|
|
|
if (Array.isArray(c))
|
|
return c
|
|
}
|
|
|
|
try {
|
|
return this._readdirEntries(abs, fs.readdirSync(abs))
|
|
} catch (er) {
|
|
this._readdirError(abs, er)
|
|
return null
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
this.cache[abs] = entries
|
|
|
|
// mark and cache dir-ness
|
|
return entries
|
|
}
|
|
|
|
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
|
|
|
|
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)
|
|
throw er
|
|
if (!this.silent)
|
|
console.error('glob error', er)
|
|
break
|
|
}
|
|
}
|
|
|
|
GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) {
|
|
|
|
var entries = this._readdir(abs, inGlobStar)
|
|
|
|
// no entries means not a dir, so it can never have matches
|
|
// foo.txt/** doesn't match foo.txt
|
|
if (!entries)
|
|
return
|
|
|
|
// 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)
|
|
}
|
|
}
|
|
|
|
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)
|
|
|
|
// If it doesn't exist, then just mark the lack of results
|
|
if (!exists)
|
|
return
|
|
|
|
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 (process.platform === 'win32')
|
|
prefix = prefix.replace(/\\/g, '/')
|
|
|
|
// Mark this as a match
|
|
this.matches[index][prefix] = true
|
|
}
|
|
|
|
// Returns either 'DIR', 'FILE', or false
|
|
GlobSync.prototype._stat = function (f) {
|
|
var abs = this._makeAbs(f)
|
|
var needDir = f.slice(-1) === '/'
|
|
|
|
if (f.length > this.maxLength)
|
|
return false
|
|
|
|
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 c
|
|
|
|
if (needDir && c === 'FILE')
|
|
return false
|
|
|
|
// otherwise we have to stat, because maybe c=true
|
|
// if we know it exists, but not what it is.
|
|
}
|
|
|
|
var exists
|
|
var stat = this.statCache[abs]
|
|
if (!stat) {
|
|
var lstat
|
|
try {
|
|
lstat = fs.lstatSync(abs)
|
|
} catch (er) {
|
|
return false
|
|
}
|
|
|
|
if (lstat.isSymbolicLink()) {
|
|
try {
|
|
stat = fs.statSync(abs)
|
|
} catch (er) {
|
|
stat = lstat
|
|
}
|
|
} else {
|
|
stat = lstat
|
|
}
|
|
}
|
|
|
|
this.statCache[abs] = stat
|
|
|
|
var c = stat.isDirectory() ? 'DIR' : 'FILE'
|
|
this.cache[abs] = this.cache[abs] || c
|
|
|
|
if (needDir && c !== 'DIR')
|
|
return false
|
|
|
|
return c
|
|
}
|
|
|
|
GlobSync.prototype._mark = function (p) {
|
|
return common.mark(this, p)
|
|
}
|
|
|
|
GlobSync.prototype._makeAbs = function (f) {
|
|
return common.makeAbs(this, f)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 257 */
|
|
/***/ (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
|
|
|
|
function ownProp (obj, field) {
|
|
return Object.prototype.hasOwnProperty.call(obj, field)
|
|
}
|
|
|
|
var path = __webpack_require__(57)
|
|
var minimatch = __webpack_require__(201)
|
|
var isAbsolute = __webpack_require__(245)
|
|
var Minimatch = minimatch.Minimatch
|
|
|
|
function alphasorti (a, b) {
|
|
return a.toLowerCase().localeCompare(b.toLowerCase())
|
|
}
|
|
|
|
function alphasort (a, b) {
|
|
return a.localeCompare(b)
|
|
}
|
|
|
|
function setupIgnores (self, options) {
|
|
self.ignore = options.ignore || []
|
|
|
|
if (!Array.isArray(self.ignore))
|
|
self.ignore = [self.ignore]
|
|
|
|
if (self.ignore.length) {
|
|
self.ignore = self.ignore.map(ignoreMap)
|
|
}
|
|
}
|
|
|
|
// 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 })
|
|
}
|
|
|
|
return {
|
|
matcher: new Minimatch(pattern, { dot: true }),
|
|
gmatcher: gmatcher
|
|
}
|
|
}
|
|
|
|
function setopts (self, pattern, options) {
|
|
if (!options)
|
|
options = {}
|
|
|
|
// 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
|
|
}
|
|
|
|
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)
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
|
|
// 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
|
|
}
|
|
|
|
function finish (self) {
|
|
var nou = self.nounique
|
|
var all = nou ? [] : Object.create(null)
|
|
|
|
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
|
|
})
|
|
}
|
|
}
|
|
|
|
if (!nou)
|
|
all = Object.keys(all)
|
|
|
|
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))
|
|
})
|
|
}
|
|
}
|
|
|
|
if (self.ignore.length)
|
|
all = all.filter(function(m) {
|
|
return !isIgnored(self, m)
|
|
})
|
|
|
|
self.found = all
|
|
}
|
|
|
|
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) === '/'
|
|
|
|
if (isDir && !slash)
|
|
m += '/'
|
|
else if (!isDir && slash)
|
|
m = m.slice(0, -1)
|
|
|
|
if (m !== p) {
|
|
var mabs = makeAbs(self, m)
|
|
self.statCache[mabs] = self.statCache[abs]
|
|
self.cache[mabs] = self.cache[abs]
|
|
}
|
|
}
|
|
|
|
return m
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
|
|
// 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
|
|
|
|
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
|
|
|
|
return self.ignore.some(function(item) {
|
|
return !!(item.gmatcher && item.gmatcher.match(path))
|
|
})
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 258 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var cc = __webpack_require__(259)
|
|
var join = __webpack_require__(57).join
|
|
var deepExtend = __webpack_require__(262)
|
|
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__(263)(process.argv.slice(2))
|
|
defaults = (
|
|
'string' === typeof defaults
|
|
? cc.json(defaults) : defaults
|
|
) || {}
|
|
|
|
parse = parse || cc.parse
|
|
|
|
var env = cc.env(name + '_')
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
|
|
return deepExtend.apply(null, configs.concat([
|
|
env,
|
|
argv,
|
|
configFiles.length ? {configs: configFiles, config: configFiles[configFiles.length - 1]} : undefined,
|
|
]))
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 259 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
var fs = __webpack_require__(55)
|
|
var ini = __webpack_require__(260)
|
|
var path = __webpack_require__(57)
|
|
var stripJsonComments = __webpack_require__(261)
|
|
|
|
var parse = exports.parse = function (content) {
|
|
|
|
//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(/^\s*{/.test(content))
|
|
return JSON.parse(stripJsonComments(content))
|
|
return ini.parse(content)
|
|
|
|
}
|
|
|
|
var file = exports.file = function () {
|
|
var args = [].slice.call(arguments).filter(function (arg) { return arg != null })
|
|
|
|
//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
|
|
}
|
|
}
|
|
|
|
var json = exports.json = function () {
|
|
var content = file.apply(null, arguments)
|
|
return content ? parse(content) : null
|
|
}
|
|
|
|
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('__')
|
|
|
|
// Trim empty strings from keypath array
|
|
var _emptyStringIndex
|
|
while ((_emptyStringIndex=keypath.indexOf('')) > -1) {
|
|
keypath.splice(_emptyStringIndex, 1)
|
|
}
|
|
|
|
var cursor = obj
|
|
keypath.forEach(function _buildSubObj(_subkey,i){
|
|
|
|
// (check for _subkey first so we ignore empty strings)
|
|
// (check for cursor to avoid assignment to primitive objects)
|
|
if (!_subkey || typeof cursor !== 'object')
|
|
return
|
|
|
|
// 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]
|
|
|
|
|
|
// 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]
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
return find(process.cwd(), rel)
|
|
}
|
|
|
|
|
|
|
|
|
|
/***/ }),
|
|
/* 260 */
|
|
/***/ (function(module, exports) {
|
|
|
|
exports.parse = exports.decode = decode
|
|
|
|
exports.stringify = exports.encode = encode
|
|
|
|
exports.safe = safe
|
|
exports.unsafe = unsafe
|
|
|
|
var eol = typeof process !== 'undefined' &&
|
|
process.platform === 'win32' ? '\r\n' : '\n'
|
|
|
|
function encode (obj, opt) {
|
|
var children = []
|
|
var out = ''
|
|
|
|
if (typeof opt === 'string') {
|
|
opt = {
|
|
section: opt,
|
|
whitespace: false
|
|
}
|
|
} else {
|
|
opt = opt || {}
|
|
opt.whitespace = opt.whitespace === true
|
|
}
|
|
|
|
var separator = opt.whitespace ? ' = ' : '='
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
})
|
|
|
|
return out
|
|
}
|
|
|
|
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')
|
|
})
|
|
}
|
|
|
|
function decode (str) {
|
|
var out = {}
|
|
var p = out
|
|
var section = null
|
|
// section |key = value
|
|
var re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i
|
|
var lines = str.split(/[\r\n]+/g)
|
|
|
|
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]]
|
|
}
|
|
}
|
|
|
|
// 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]
|
|
})
|
|
|
|
return out
|
|
}
|
|
|
|
function isQuoted (val) {
|
|
return (val.charAt(0) === '"' && val.slice(-1) === '"') ||
|
|
(val.charAt(0) === "'" && val.slice(-1) === "'")
|
|
}
|
|
|
|
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, '\\#')
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 261 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
var singleComment = 1;
|
|
var multiComment = 2;
|
|
|
|
function stripWithoutWhitespace() {
|
|
return '';
|
|
}
|
|
|
|
function stripWithWhitespace(str, start, end) {
|
|
return str.slice(start, end).replace(/\S/g, ' ');
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
if (insideString) {
|
|
continue;
|
|
}
|
|
|
|
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 ret + (insideComment ? strip(str.substr(offset)) : str.substr(offset));
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 262 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
/*!
|
|
* @description Recursive object extending
|
|
* @author Viacheslav Lotsmanov <lotsmanov89@gmail.com>
|
|
* @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.
|
|
*/
|
|
|
|
|
|
|
|
function isSpecificValue(val) {
|
|
return (
|
|
val instanceof Buffer
|
|
|| val instanceof Date
|
|
|| val instanceof RegExp
|
|
) ? true : false;
|
|
}
|
|
|
|
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');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
if (arguments.length < 2) {
|
|
return arguments[0];
|
|
}
|
|
|
|
var target = arguments[0];
|
|
|
|
// convert arguments to array and cut off target object
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
|
|
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;
|
|
}
|
|
|
|
Object.keys(obj).forEach(function (key) {
|
|
src = safeGetProperty(target, key); // source value
|
|
val = safeGetProperty(obj, key); // new value
|
|
|
|
// 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;
|
|
|
|
// just clone arrays (and recursive clone objects inside)
|
|
} else if (Array.isArray(val)) {
|
|
target[key] = deepCloneArray(val);
|
|
return;
|
|
|
|
// custom cloning and overwrite for specific objects
|
|
} else if (isSpecificValue(val)) {
|
|
target[key] = cloneSpecificValue(val);
|
|
return;
|
|
|
|
// 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;
|
|
|
|
// source value and new value is objects both, extending...
|
|
} else {
|
|
target[key] = deepExtend(src, val);
|
|
return;
|
|
}
|
|
});
|
|
});
|
|
|
|
return target;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 263 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = function (args, opts) {
|
|
if (!opts) opts = {};
|
|
|
|
var flags = { bools : {}, strings : {}, unknownFn: null };
|
|
|
|
if (typeof opts['unknown'] === 'function') {
|
|
flags.unknownFn = opts['unknown'];
|
|
}
|
|
|
|
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;
|
|
}));
|
|
});
|
|
});
|
|
|
|
[].concat(opts.string).filter(Boolean).forEach(function (key) {
|
|
flags.strings[key] = true;
|
|
if (aliases[key]) {
|
|
flags.strings[aliases[key]] = true;
|
|
}
|
|
});
|
|
|
|
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('--'));
|
|
}
|
|
|
|
function argDefined(key, arg) {
|
|
return (flags.allBools && /^--[^=]+$/.test(arg)) ||
|
|
flags.strings[key] || flags.bools[key] || aliases[key];
|
|
}
|
|
|
|
function setArg (key, val, arg) {
|
|
if (arg && flags.unknownFn && !argDefined(key, arg)) {
|
|
if (flags.unknownFn(arg) === false) return;
|
|
}
|
|
|
|
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 setKey (obj, keys, value) {
|
|
var o = obj;
|
|
keys.slice(0,-1).forEach(function (key) {
|
|
if (o[key] === undefined) o[key] = {};
|
|
o = o[key];
|
|
});
|
|
|
|
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];
|
|
});
|
|
}
|
|
|
|
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);
|
|
});
|
|
}
|
|
|
|
return argv;
|
|
};
|
|
|
|
function hasKey (obj, keys) {
|
|
var o = obj;
|
|
keys.slice(0,-1).forEach(function (key) {
|
|
o = (o[key] || {});
|
|
});
|
|
|
|
var key = keys[keys.length - 1];
|
|
return key in o;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
|
|
/***/ }),
|
|
/* 264 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("url");
|
|
|
|
/***/ }),
|
|
/* 265 */
|
|
/***/ (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__(266);
|
|
const fs_1 = tslib_1.__importDefault(__webpack_require__(55));
|
|
const mkdirp_1 = tslib_1.__importDefault(__webpack_require__(179));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const tar_1 = tslib_1.__importDefault(__webpack_require__(273));
|
|
const url_1 = __webpack_require__(264);
|
|
const fetch_1 = __webpack_require__(304);
|
|
/**
|
|
* Download and extract tgz from url
|
|
*
|
|
* @param {string} url
|
|
* @param {DownloadOptions} options contains dest folder and optional onProgress callback
|
|
*/
|
|
function download(url, options) {
|
|
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,
|
|
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
|
|
|
|
/***/ }),
|
|
/* 266 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var url = __webpack_require__(264);
|
|
var URL = url.URL;
|
|
var http = __webpack_require__(267);
|
|
var https = __webpack_require__(268);
|
|
var assert = __webpack_require__(101);
|
|
var Writable = __webpack_require__(41).Writable;
|
|
var debug = __webpack_require__(269)("follow-redirects");
|
|
|
|
// 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 };
|
|
|
|
// 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);
|
|
};
|
|
});
|
|
|
|
// 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);
|
|
}
|
|
|
|
// React to responses of native requests
|
|
var self = this;
|
|
this._onNativeResponse = function (response) {
|
|
self._processResponse(response);
|
|
};
|
|
|
|
// Perform the first request
|
|
this._performRequest();
|
|
}
|
|
RedirectableRequest.prototype = Object.create(Writable.prototype);
|
|
|
|
// 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");
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
// 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();
|
|
}
|
|
};
|
|
|
|
// 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;
|
|
}
|
|
|
|
// 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);
|
|
};
|
|
|
|
// Global timeout for all underlying requests
|
|
RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
|
|
if (callback) {
|
|
this.once("timeout", callback);
|
|
}
|
|
|
|
if (this.socket) {
|
|
startTimer(this, msecs);
|
|
}
|
|
else {
|
|
var self = this;
|
|
this._currentRequest.once("socket", function () {
|
|
startTimer(self, msecs);
|
|
});
|
|
}
|
|
|
|
this.once("response", clearTimer);
|
|
this.once("error", clearTimer);
|
|
|
|
return this;
|
|
};
|
|
|
|
function startTimer(request, msecs) {
|
|
clearTimeout(request._timeout);
|
|
request._timeout = setTimeout(function () {
|
|
request.emit("timeout");
|
|
}, msecs);
|
|
}
|
|
|
|
function clearTimer() {
|
|
clearTimeout(this._timeout);
|
|
}
|
|
|
|
// 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]; },
|
|
});
|
|
});
|
|
|
|
RedirectableRequest.prototype._sanitizeOptions = function (options) {
|
|
// Ensure headers are always present
|
|
if (!options.headers) {
|
|
options.headers = {};
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
// 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;
|
|
}
|
|
|
|
// 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);
|
|
|
|
// Set up event handlers
|
|
request._redirectable = this;
|
|
for (var event in eventHandlers) {
|
|
/* istanbul ignore else */
|
|
if (event) {
|
|
request.on(event, eventHandlers[event]);
|
|
}
|
|
}
|
|
|
|
// 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();
|
|
}
|
|
}
|
|
}());
|
|
}
|
|
};
|
|
|
|
// 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,
|
|
});
|
|
}
|
|
|
|
// 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();
|
|
|
|
// 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;
|
|
}
|
|
|
|
// 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];
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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];
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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();
|
|
}
|
|
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 = [];
|
|
}
|
|
};
|
|
|
|
// 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;
|
|
}
|
|
|
|
/* 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 options;
|
|
}
|
|
|
|
// Exports
|
|
module.exports = wrap({ http: http, https: https });
|
|
module.exports.wrap = wrap;
|
|
|
|
|
|
/***/ }),
|
|
/* 267 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("http");
|
|
|
|
/***/ }),
|
|
/* 268 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("https");
|
|
|
|
/***/ }),
|
|
/* 269 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
/**
|
|
* 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__(270);
|
|
} else {
|
|
module.exports = __webpack_require__(272);
|
|
}
|
|
|
|
|
|
|
|
/***/ }),
|
|
/* 270 */
|
|
/***/ (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); }
|
|
|
|
/* eslint-env browser */
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
|
|
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
|
|
|
|
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.
|
|
|
|
|
|
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 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
|
|
*/
|
|
|
|
|
|
function formatArgs(args) {
|
|
args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + '+' + module.exports.humanize(this.diff);
|
|
|
|
if (!this.useColors) {
|
|
return;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
index++;
|
|
|
|
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
|
|
*/
|
|
|
|
|
|
function log() {
|
|
var _console;
|
|
|
|
// 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
|
|
*/
|
|
|
|
|
|
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
|
|
*/
|
|
|
|
|
|
function load() {
|
|
var r;
|
|
|
|
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
|
|
|
|
|
|
if (!r && typeof process !== 'undefined' && 'env' in process) {
|
|
r = process.env.DEBUG;
|
|
}
|
|
|
|
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
|
|
*/
|
|
|
|
|
|
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?
|
|
}
|
|
}
|
|
|
|
module.exports = __webpack_require__(271)(exports);
|
|
var formatters = module.exports.formatters;
|
|
/**
|
|
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
|
|
*/
|
|
|
|
formatters.j = function (v) {
|
|
try {
|
|
return JSON.stringify(v);
|
|
} catch (error) {
|
|
return '[UnexpectedJSONParseError]: ' + error.message;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/***/ }),
|
|
/* 271 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
/**
|
|
* 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__(68);
|
|
Object.keys(env).forEach(function (key) {
|
|
createDebug[key] = env[key];
|
|
});
|
|
/**
|
|
* Active `debug` instances.
|
|
*/
|
|
|
|
createDebug.instances = [];
|
|
/**
|
|
* The currently active debug mode names, and names to skip.
|
|
*/
|
|
|
|
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".
|
|
*/
|
|
|
|
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
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
args[_key] = arguments[_key];
|
|
}
|
|
|
|
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]);
|
|
|
|
if (typeof args[0] !== 'string') {
|
|
// Anything else let's inspect with %O
|
|
args.unshift('%O');
|
|
} // Apply any `formatters` transformations
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
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`
|
|
|
|
args.splice(index, 1);
|
|
index--;
|
|
}
|
|
|
|
return match;
|
|
}); // Apply env-specific formatting (colors, etc.)
|
|
|
|
createDebug.formatArgs.call(self, args);
|
|
var logFn = self.log || createDebug.log;
|
|
logFn.apply(self, args);
|
|
}
|
|
|
|
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 (typeof createDebug.init === 'function') {
|
|
createDebug.init(debug);
|
|
}
|
|
|
|
createDebug.instances.push(debug);
|
|
return debug;
|
|
}
|
|
|
|
function destroy() {
|
|
var index = createDebug.instances.indexOf(this);
|
|
|
|
if (index !== -1) {
|
|
createDebug.instances.splice(index, 1);
|
|
return true;
|
|
}
|
|
|
|
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
|
|
*/
|
|
|
|
|
|
function enable(namespaces) {
|
|
createDebug.save(namespaces);
|
|
createDebug.names = [];
|
|
createDebug.skips = [];
|
|
var i;
|
|
var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
|
|
var len = split.length;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if (!split[i]) {
|
|
// ignore empty strings
|
|
continue;
|
|
}
|
|
|
|
namespaces = split[i].replace(/\*/g, '.*?');
|
|
|
|
if (namespaces[0] === '-') {
|
|
createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
|
|
} else {
|
|
createDebug.names.push(new RegExp('^' + namespaces + '$'));
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < createDebug.instances.length; i++) {
|
|
var instance = createDebug.instances[i];
|
|
instance.enabled = createDebug.enabled(instance.namespace);
|
|
}
|
|
}
|
|
/**
|
|
* Disable debug output.
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
|
|
function disable() {
|
|
createDebug.enable('');
|
|
}
|
|
/**
|
|
* Returns true if the given mode name is enabled, false otherwise.
|
|
*
|
|
* @param {String} name
|
|
* @return {Boolean}
|
|
* @api public
|
|
*/
|
|
|
|
|
|
function enabled(name) {
|
|
if (name[name.length - 1] === '*') {
|
|
return true;
|
|
}
|
|
|
|
var i;
|
|
var len;
|
|
|
|
for (i = 0, len = createDebug.skips.length; i < len; i++) {
|
|
if (createDebug.skips[i].test(name)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
for (i = 0, len = createDebug.names.length; i < len; i++) {
|
|
if (createDebug.names[i].test(name)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
/**
|
|
* Coerce `val`.
|
|
*
|
|
* @param {Mixed} val
|
|
* @return {Mixed}
|
|
* @api private
|
|
*/
|
|
|
|
|
|
function coerce(val) {
|
|
if (val instanceof Error) {
|
|
return val.stack || val.message;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
createDebug.enable(createDebug.load());
|
|
return createDebug;
|
|
}
|
|
|
|
module.exports = setup;
|
|
|
|
|
|
|
|
/***/ }),
|
|
/* 272 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
/**
|
|
* Module dependencies.
|
|
*/
|
|
var tty = __webpack_require__(70);
|
|
|
|
var util = __webpack_require__(40);
|
|
/**
|
|
* 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__(71);
|
|
|
|
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.
|
|
|
|
/**
|
|
* Build up the default `inspectOpts` object from the environment variables.
|
|
*
|
|
* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
|
|
*/
|
|
|
|
|
|
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 {
|
|
val = Number(val);
|
|
}
|
|
|
|
obj[prop] = val;
|
|
return obj;
|
|
}, {});
|
|
/**
|
|
* Is stdout a TTY? Colored output is enabled when `true`.
|
|
*/
|
|
|
|
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
|
|
*/
|
|
|
|
|
|
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];
|
|
}
|
|
}
|
|
|
|
function getDate() {
|
|
if (exports.inspectOpts.hideDate) {
|
|
return '';
|
|
}
|
|
|
|
return new Date().toISOString() + ' ';
|
|
}
|
|
/**
|
|
* Invokes `util.format()` with the specified arguments and writes to stderr.
|
|
*/
|
|
|
|
|
|
function log() {
|
|
return process.stderr.write(util.format.apply(util, arguments) + '\n');
|
|
}
|
|
/**
|
|
* Save `namespaces`.
|
|
*
|
|
* @param {String} namespaces
|
|
* @api private
|
|
*/
|
|
|
|
|
|
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
|
|
*/
|
|
|
|
|
|
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 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]];
|
|
}
|
|
}
|
|
|
|
module.exports = __webpack_require__(271)(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);
|
|
};
|
|
|
|
|
|
|
|
/***/ }),
|
|
/* 273 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
// high-level commands
|
|
exports.c = exports.create = __webpack_require__(274)
|
|
exports.r = exports.replace = __webpack_require__(298)
|
|
exports.t = exports.list = __webpack_require__(296)
|
|
exports.u = exports.update = __webpack_require__(299)
|
|
exports.x = exports.extract = __webpack_require__(300)
|
|
|
|
// classes
|
|
exports.Pack = __webpack_require__(276)
|
|
exports.Unpack = __webpack_require__(301)
|
|
exports.Parse = __webpack_require__(297)
|
|
exports.ReadEntry = __webpack_require__(286)
|
|
exports.WriteEntry = __webpack_require__(288)
|
|
exports.Header = __webpack_require__(290)
|
|
exports.Pax = __webpack_require__(289)
|
|
exports.types = __webpack_require__(287)
|
|
|
|
|
|
/***/ }),
|
|
/* 274 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
// tar -c
|
|
const hlo = __webpack_require__(275)
|
|
|
|
const Pack = __webpack_require__(276)
|
|
const fs = __webpack_require__(55)
|
|
const fsm = __webpack_require__(295)
|
|
const t = __webpack_require__(296)
|
|
const path = __webpack_require__(57)
|
|
|
|
const c = module.exports = (opt_, files, cb) => {
|
|
if (typeof files === 'function')
|
|
cb = files
|
|
|
|
if (Array.isArray(opt_))
|
|
files = opt_, opt_ = {}
|
|
|
|
if (!files || !Array.isArray(files) || !files.length)
|
|
throw new TypeError('no files or directories specified')
|
|
|
|
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')
|
|
|
|
return opt.file && opt.sync ? createFileSync(opt, files)
|
|
: opt.file ? createFile(opt, files, cb)
|
|
: opt.sync ? createSync(opt, files)
|
|
: create(opt, files)
|
|
}
|
|
|
|
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)
|
|
|
|
const promise = new Promise((res, rej) => {
|
|
stream.on('error', rej)
|
|
stream.on('close', res)
|
|
p.on('error', rej)
|
|
})
|
|
|
|
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()
|
|
}
|
|
|
|
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()
|
|
}
|
|
|
|
const createSync = (opt, files) => {
|
|
const p = new Pack.Sync(opt)
|
|
addFilesSync(p, files)
|
|
return p
|
|
}
|
|
|
|
const create = (opt, files) => {
|
|
const p = new Pack(opt)
|
|
addFilesAsync(p, files)
|
|
return p
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 275 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
// turn tar(1) style args like `C` into the more verbose things like `cwd`
|
|
|
|
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']
|
|
])
|
|
|
|
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)) : {}
|
|
|
|
|
|
/***/ }),
|
|
/* 276 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const Buffer = __webpack_require__(277)
|
|
|
|
// 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
|
|
}
|
|
}
|
|
|
|
const MiniPass = __webpack_require__(280)
|
|
const zlib = __webpack_require__(284)
|
|
const ReadEntry = __webpack_require__(286)
|
|
const WriteEntry = __webpack_require__(288)
|
|
const WriteEntrySync = WriteEntry.Sync
|
|
const WriteEntryTar = WriteEntry.Tar
|
|
const Yallist = __webpack_require__(281)
|
|
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')
|
|
|
|
const fs = __webpack_require__(55)
|
|
const path = __webpack_require__(57)
|
|
const warner = __webpack_require__(292)
|
|
|
|
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
|
|
}
|
|
|
|
[WRITE] (chunk) {
|
|
return super.write(chunk)
|
|
}
|
|
|
|
add (path) {
|
|
this.write(path)
|
|
return this
|
|
}
|
|
|
|
end (path) {
|
|
if (path)
|
|
this.write(path)
|
|
this[ENDED] = true
|
|
this[PROCESS]()
|
|
return this
|
|
}
|
|
|
|
write (path) {
|
|
if (this[ENDED])
|
|
throw new Error('write after end')
|
|
|
|
if (path instanceof ReadEntry)
|
|
this[ADDTARENTRY](path)
|
|
else
|
|
this[ADDFSENTRY](path)
|
|
return this.flowing
|
|
}
|
|
|
|
[ADDTARENTRY] (p) {
|
|
const absolute = path.resolve(this.cwd, p.path)
|
|
if (this.prefix)
|
|
p.path = this.prefix + '/' + p.path.replace(/^\.(\/+|$)/, '')
|
|
|
|
// 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)
|
|
}
|
|
|
|
this[PROCESS]()
|
|
}
|
|
|
|
[ADDFSENTRY] (p) {
|
|
const absolute = path.resolve(this.cwd, p)
|
|
if (this.prefix)
|
|
p = this.prefix + '/' + p.replace(/^\.(\/+|$)/, '')
|
|
|
|
this[QUEUE].push(new PackJob(p, absolute))
|
|
this[PROCESS]()
|
|
}
|
|
|
|
[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)
|
|
})
|
|
}
|
|
|
|
[ONSTAT] (job, stat) {
|
|
this.statCache.set(job.absolute, stat)
|
|
job.stat = stat
|
|
|
|
// now we have the stat, we can filter it.
|
|
if (!this.filter(job.path, stat))
|
|
job.ignore = true
|
|
|
|
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]()
|
|
}
|
|
|
|
[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
|
|
}
|
|
}
|
|
|
|
this[PROCESSING] = false
|
|
|
|
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
|
|
}
|
|
|
|
[JOBDONE] (job) {
|
|
this[QUEUE].shift()
|
|
this[JOBS] -= 1
|
|
this[PROCESS]()
|
|
}
|
|
|
|
[PROCESSJOB] (job) {
|
|
if (job.pending)
|
|
return
|
|
|
|
if (job.entry) {
|
|
if (job === this[CURRENT] && !job.piped)
|
|
this[PIPE](job)
|
|
return
|
|
}
|
|
|
|
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
|
|
|
|
// filtered out!
|
|
if (job.ignore)
|
|
return
|
|
|
|
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
|
|
}
|
|
|
|
// 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 (job === this[CURRENT] && !job.piped)
|
|
this[PIPE](job)
|
|
}
|
|
|
|
[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
|
|
}
|
|
}
|
|
|
|
[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)
|
|
}
|
|
}
|
|
|
|
[ONDRAIN] () {
|
|
if (this[CURRENT] && this[CURRENT].entry)
|
|
this[CURRENT].entry.resume()
|
|
}
|
|
|
|
// 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()
|
|
})
|
|
}
|
|
|
|
pause () {
|
|
if (this.zip)
|
|
this.zip.pause()
|
|
return super.pause()
|
|
}
|
|
})
|
|
|
|
class PackSync extends Pack {
|
|
constructor (opt) {
|
|
super(opt)
|
|
this[WRITEENTRYCLASS] = WriteEntrySync
|
|
}
|
|
|
|
// pause/resume are no-ops in sync streams.
|
|
pause () {}
|
|
resume () {}
|
|
|
|
[STAT] (job) {
|
|
const stat = this.follow ? 'statSync' : 'lstatSync'
|
|
this[ONSTAT](job, fs[stat](job.absolute))
|
|
}
|
|
|
|
[READDIR] (job, stat) {
|
|
this[ONREADDIR](job, fs.readdirSync(job.absolute))
|
|
}
|
|
|
|
// 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
|
|
|
|
|
|
/***/ }),
|
|
/* 277 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
// 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__(278).Buffer
|
|
}
|
|
module.exports = B
|
|
|
|
|
|
/***/ }),
|
|
/* 278 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* eslint-disable node/no-deprecated-api */
|
|
var buffer = __webpack_require__(279)
|
|
var Buffer = buffer.Buffer
|
|
|
|
// 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
|
|
}
|
|
|
|
function SafeBuffer (arg, encodingOrOffset, length) {
|
|
return Buffer(arg, encodingOrOffset, length)
|
|
}
|
|
|
|
// Copy static methods from Buffer
|
|
copyProps(Buffer, SafeBuffer)
|
|
|
|
SafeBuffer.from = function (arg, encodingOrOffset, length) {
|
|
if (typeof arg === 'number') {
|
|
throw new TypeError('Argument must not be a number')
|
|
}
|
|
return Buffer(arg, encodingOrOffset, length)
|
|
}
|
|
|
|
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)
|
|
}
|
|
} else {
|
|
buf.fill(0)
|
|
}
|
|
return buf
|
|
}
|
|
|
|
SafeBuffer.allocUnsafe = function (size) {
|
|
if (typeof size !== 'number') {
|
|
throw new TypeError('Argument must be a number')
|
|
}
|
|
return Buffer(size)
|
|
}
|
|
|
|
SafeBuffer.allocUnsafeSlow = function (size) {
|
|
if (typeof size !== 'number') {
|
|
throw new TypeError('Argument must be a number')
|
|
}
|
|
return buffer.SlowBuffer(size)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 279 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("buffer");
|
|
|
|
/***/ }),
|
|
/* 280 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
const EE = __webpack_require__(49)
|
|
const Yallist = __webpack_require__(281)
|
|
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__(283).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__(278).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
|
|
}
|
|
|
|
get bufferLength () { return this[BUFFERLENGTH] }
|
|
|
|
get encoding () { return this[ENCODING] }
|
|
set encoding (enc) {
|
|
if (this[OBJECTMODE])
|
|
throw new Error('cannot set encoding in objectMode')
|
|
|
|
if (this[ENCODING] && enc !== this[ENCODING] &&
|
|
(this[DECODER] && this[DECODER].lastNeed || this[BUFFERLENGTH]))
|
|
throw new Error('cannot change encoding')
|
|
|
|
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
|
|
}
|
|
|
|
setEncoding (enc) {
|
|
this.encoding = enc
|
|
}
|
|
|
|
write (chunk, encoding, cb) {
|
|
if (this[EOF])
|
|
throw new Error('write after end')
|
|
|
|
if (typeof encoding === 'function')
|
|
cb = encoding, encoding = 'utf8'
|
|
|
|
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)
|
|
}
|
|
|
|
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()
|
|
}
|
|
}
|
|
|
|
read (n) {
|
|
try {
|
|
if (this[BUFFERLENGTH] === 0 || n === 0 || n > this[BUFFERLENGTH])
|
|
return null
|
|
|
|
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])
|
|
])
|
|
}
|
|
|
|
return this[READ](n || null, this.buffer.head.value)
|
|
} finally {
|
|
this[MAYBE_EMIT_END]()
|
|
}
|
|
}
|
|
|
|
[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
|
|
}
|
|
|
|
this.emit('data', chunk)
|
|
|
|
if (!this.buffer.length && !this[EOF])
|
|
this.emit('drain')
|
|
|
|
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]()
|
|
}
|
|
|
|
// 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')
|
|
}
|
|
|
|
resume () {
|
|
return this[RESUME]()
|
|
}
|
|
|
|
pause () {
|
|
this[FLOWING] = false
|
|
}
|
|
|
|
get flowing () {
|
|
return this[FLOWING]
|
|
}
|
|
|
|
[BUFFERPUSH] (chunk) {
|
|
if (this[OBJECTMODE])
|
|
this[BUFFERLENGTH] += 1
|
|
else
|
|
this[BUFFERLENGTH] += chunk.length
|
|
return this.buffer.push(chunk)
|
|
}
|
|
|
|
[BUFFERSHIFT] () {
|
|
if (this.buffer.length) {
|
|
if (this[OBJECTMODE])
|
|
this[BUFFERLENGTH] -= 1
|
|
else
|
|
this[BUFFERLENGTH] -= this.buffer.head.value.length
|
|
}
|
|
return this.buffer.shift()
|
|
}
|
|
|
|
[FLUSH] () {
|
|
do {} while (this[FLUSHCHUNK](this[BUFFERSHIFT]()))
|
|
|
|
if (!this.buffer.length && !this[EOF])
|
|
this.emit('drain')
|
|
}
|
|
|
|
[FLUSHCHUNK] (chunk) {
|
|
return chunk ? (this.emit('data', chunk), this.flowing) : false
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
addListener (ev, fn) {
|
|
return this.on(ev, fn)
|
|
}
|
|
|
|
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')
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
|
|
if (this.pipes.length)
|
|
this.pipes.forEach(p => p.dest.write(data) || this.pause())
|
|
} else if (ev === 'end') {
|
|
if (this[EMITTED_END] === true)
|
|
return
|
|
|
|
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.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
|
|
}
|
|
|
|
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]
|
|
}
|
|
}
|
|
|
|
try {
|
|
return super.emit.apply(this, args)
|
|
} finally {
|
|
if (ev !== 'end')
|
|
this[MAYBE_EMIT_END]()
|
|
else
|
|
this.removeAllListeners('end')
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
})
|
|
}
|
|
|
|
// for await (let chunk of stream)
|
|
[ASYNCITERATOR] () {
|
|
const next = () => {
|
|
const res = this.read()
|
|
if (res !== null)
|
|
return Promise.resolve({ done: false, value: res })
|
|
|
|
if (this[EOF])
|
|
return Promise.resolve({ done: true })
|
|
|
|
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 { next }
|
|
}
|
|
|
|
// for (let chunk of stream)
|
|
[ITERATOR] () {
|
|
const next = () => {
|
|
const value = this.read()
|
|
const done = value === null
|
|
return { value, done }
|
|
}
|
|
return { next }
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 281 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
module.exports = Yallist
|
|
|
|
Yallist.Node = Node
|
|
Yallist.create = Yallist
|
|
|
|
function Yallist (list) {
|
|
var self = this
|
|
if (!(self instanceof Yallist)) {
|
|
self = new Yallist()
|
|
}
|
|
|
|
self.tail = null
|
|
self.head = null
|
|
self.length = 0
|
|
|
|
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])
|
|
}
|
|
}
|
|
|
|
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
|
|
|
|
if (next) {
|
|
next.prev = prev
|
|
}
|
|
|
|
if (prev) {
|
|
prev.next = next
|
|
}
|
|
|
|
if (node === this.head) {
|
|
this.head = next
|
|
}
|
|
if (node === this.tail) {
|
|
this.tail = prev
|
|
}
|
|
|
|
node.list.length--
|
|
node.next = null
|
|
node.prev = null
|
|
node.list = null
|
|
}
|
|
|
|
Yallist.prototype.unshiftNode = function (node) {
|
|
if (node === this.head) {
|
|
return
|
|
}
|
|
|
|
if (node.list) {
|
|
node.list.removeNode(node)
|
|
}
|
|
|
|
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++
|
|
}
|
|
|
|
Yallist.prototype.pushNode = function (node) {
|
|
if (node === this.tail) {
|
|
return
|
|
}
|
|
|
|
if (node.list) {
|
|
node.list.removeNode(node)
|
|
}
|
|
|
|
var tail = this.tail
|
|
node.list = this
|
|
node.prev = tail
|
|
if (tail) {
|
|
tail.next = node
|
|
}
|
|
|
|
this.tail = node
|
|
if (!this.head) {
|
|
this.head = node
|
|
}
|
|
this.length++
|
|
}
|
|
|
|
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])
|
|
}
|
|
return this.length
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
Yallist.prototype.shift = function () {
|
|
if (!this.head) {
|
|
return undefined
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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')
|
|
}
|
|
|
|
for (var i = 0; walker !== null; i++) {
|
|
acc = fn(acc, walker.value, i)
|
|
walker = walker.next
|
|
}
|
|
|
|
return acc
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
return acc
|
|
}
|
|
|
|
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
|
|
}
|
|
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)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
function push (self, item) {
|
|
self.tail = new Node(item, self.tail, null, self)
|
|
if (!self.head) {
|
|
self.head = self.tail
|
|
}
|
|
self.length++
|
|
}
|
|
|
|
function unshift (self, item) {
|
|
self.head = new Node(item, null, self.head, self)
|
|
if (!self.tail) {
|
|
self.tail = self.head
|
|
}
|
|
self.length++
|
|
}
|
|
|
|
function Node (value, prev, next, list) {
|
|
if (!(this instanceof Node)) {
|
|
return new Node(value, prev, next, list)
|
|
}
|
|
|
|
this.list = list
|
|
this.value = value
|
|
|
|
if (prev) {
|
|
prev.next = this
|
|
this.prev = prev
|
|
} else {
|
|
this.prev = null
|
|
}
|
|
|
|
if (next) {
|
|
next.prev = this
|
|
this.next = next
|
|
} else {
|
|
this.next = null
|
|
}
|
|
}
|
|
|
|
try {
|
|
// add if support for Symbol.iterator is present
|
|
__webpack_require__(282)(Yallist)
|
|
} catch (er) {}
|
|
|
|
|
|
/***/ }),
|
|
/* 282 */
|
|
/***/ (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
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 283 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("string_decoder");
|
|
|
|
/***/ }),
|
|
/* 284 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const assert = __webpack_require__(101)
|
|
const Buffer = __webpack_require__(279).Buffer
|
|
const realZlib = __webpack_require__(137)
|
|
|
|
const constants = exports.constants = __webpack_require__(285)
|
|
const MiniPass = __webpack_require__(280)
|
|
|
|
const OriginalBufferConcat = Buffer.concat
|
|
|
|
class ZlibError extends Error {
|
|
constructor (msg, errno) {
|
|
super('zlib: ' + msg)
|
|
this.errno = errno
|
|
this.code = codes.get(errno)
|
|
}
|
|
|
|
get name () {
|
|
return 'ZlibError'
|
|
}
|
|
}
|
|
|
|
// 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']
|
|
])
|
|
|
|
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 strategies = new Set([
|
|
constants.Z_FILTERED,
|
|
constants.Z_HUFFMAN_ONLY,
|
|
constants.Z_RLE,
|
|
constants.Z_FIXED,
|
|
constants.Z_DEFAULT_STRATEGY
|
|
])
|
|
|
|
// 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')
|
|
|
|
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)
|
|
}
|
|
|
|
this[_flushFlag] = opts.flush || constants.Z_NO_FLUSH
|
|
this[_finishFlush] = typeof opts.finishFlush !== 'undefined' ?
|
|
opts.finishFlush : constants.Z_FINISH
|
|
|
|
if (opts.chunkSize) {
|
|
if (opts.chunkSize < constants.Z_MIN_CHUNK) {
|
|
throw new RangeError('Invalid chunk size: ' + opts.chunkSize)
|
|
}
|
|
}
|
|
|
|
if (opts.windowBits) {
|
|
if (opts.windowBits < constants.Z_MIN_WINDOWBITS ||
|
|
opts.windowBits > constants.Z_MAX_WINDOWBITS) {
|
|
throw new RangeError('Invalid windowBits: ' + opts.windowBits)
|
|
}
|
|
}
|
|
|
|
if (opts.level) {
|
|
if (opts.level < constants.Z_MIN_LEVEL ||
|
|
opts.level > constants.Z_MAX_LEVEL) {
|
|
throw new RangeError('Invalid compression level: ' + opts.level)
|
|
}
|
|
}
|
|
|
|
if (opts.memLevel) {
|
|
if (opts.memLevel < constants.Z_MIN_MEMLEVEL ||
|
|
opts.memLevel > constants.Z_MAX_MEMLEVEL) {
|
|
throw new RangeError('Invalid memLevel: ' + opts.memLevel)
|
|
}
|
|
}
|
|
|
|
if (opts.strategy && !(strategies.has(opts.strategy)))
|
|
throw new TypeError('Invalid strategy: ' + opts.strategy)
|
|
|
|
if (opts.dictionary) {
|
|
if (!(opts.dictionary instanceof Buffer)) {
|
|
throw new TypeError('Invalid dictionary: it should be a Buffer instance')
|
|
}
|
|
}
|
|
|
|
this[_handle] = new realZlib[mode](opts)
|
|
|
|
this[_onError] = (err) => {
|
|
// there is no way to cleanly recover.
|
|
// continuing only obscures problems.
|
|
this.close()
|
|
|
|
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
|
|
|
|
var strategy = typeof opts.strategy === 'number' ? opts.strategy
|
|
: constants.Z_DEFAULT_STRATEGY
|
|
|
|
// API changed in node v9
|
|
/* istanbul ignore next */
|
|
|
|
this[_level] = level
|
|
this[_strategy] = strategy
|
|
|
|
this.once('end', this.close)
|
|
}
|
|
|
|
close () {
|
|
if (this[_handle]) {
|
|
this[_handle].close()
|
|
this[_handle] = null
|
|
this.emit('close')
|
|
}
|
|
}
|
|
|
|
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')
|
|
|
|
if (level < constants.Z_MIN_LEVEL ||
|
|
level > constants.Z_MAX_LEVEL) {
|
|
throw new RangeError('Invalid compression level: ' + level)
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
}
|
|
|
|
reset () {
|
|
assert(this[_handle], 'zlib binding closed')
|
|
return this[_handle].reset()
|
|
}
|
|
|
|
flush (kind) {
|
|
if (kind === undefined)
|
|
kind = constants.Z_FULL_FLUSH
|
|
|
|
if (this.ended)
|
|
return
|
|
|
|
const flushFlag = this[_flushFlag]
|
|
this[_flushFlag] = kind
|
|
this.write(Buffer.alloc(0))
|
|
this[_flushFlag] = flushFlag
|
|
}
|
|
|
|
end (chunk, encoding, cb) {
|
|
if (chunk)
|
|
this.write(chunk, encoding)
|
|
this.flush(this[_finishFlush])
|
|
this[_ended] = true
|
|
return super.end(null, null, cb)
|
|
}
|
|
|
|
get ended () {
|
|
return this[_ended]
|
|
}
|
|
|
|
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'
|
|
|
|
if (typeof chunk === 'string')
|
|
chunk = Buffer.from(chunk, encoding)
|
|
|
|
assert(this[_handle], 'zlib binding closed')
|
|
|
|
// _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')
|
|
}
|
|
}
|
|
|
|
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))
|
|
}
|
|
}
|
|
|
|
if (cb)
|
|
cb()
|
|
return writeReturn
|
|
}
|
|
}
|
|
|
|
// minimal 2-byte header
|
|
class Deflate extends Zlib {
|
|
constructor (opts) {
|
|
super(opts, 'Deflate')
|
|
}
|
|
}
|
|
|
|
class Inflate extends Zlib {
|
|
constructor (opts) {
|
|
super(opts, 'Inflate')
|
|
}
|
|
}
|
|
|
|
// gzip - bigger header, same deflate compression
|
|
class Gzip extends Zlib {
|
|
constructor (opts) {
|
|
super(opts, 'Gzip')
|
|
}
|
|
}
|
|
|
|
class Gunzip extends Zlib {
|
|
constructor (opts) {
|
|
super(opts, 'Gunzip')
|
|
}
|
|
}
|
|
|
|
// raw - no header
|
|
class DeflateRaw extends Zlib {
|
|
constructor (opts) {
|
|
super(opts, 'DeflateRaw')
|
|
}
|
|
}
|
|
|
|
class InflateRaw extends Zlib {
|
|
constructor (opts) {
|
|
super(opts, 'InflateRaw')
|
|
}
|
|
}
|
|
|
|
// auto-detect header.
|
|
class Unzip extends Zlib {
|
|
constructor (opts) {
|
|
super(opts, 'Unzip')
|
|
}
|
|
}
|
|
|
|
exports.Deflate = Deflate
|
|
exports.Inflate = Inflate
|
|
exports.Gzip = Gzip
|
|
exports.Gunzip = Gunzip
|
|
exports.DeflateRaw = DeflateRaw
|
|
exports.InflateRaw = InflateRaw
|
|
exports.Unzip = Unzip
|
|
|
|
|
|
/***/ }),
|
|
/* 285 */
|
|
/***/ (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
|
|
})
|
|
|
|
|
|
/***/ }),
|
|
/* 286 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
const types = __webpack_require__(287)
|
|
const MiniPass = __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
|
|
|
|
case 'NextFileHasLongLinkpath':
|
|
case 'NextFileHasLongPath':
|
|
case 'OldGnuLongPath':
|
|
case 'GlobalExtendedHeader':
|
|
case 'ExtendedHeader':
|
|
case 'OldExtendedHeader':
|
|
this.meta = true
|
|
break
|
|
|
|
// NOTE: gnutar and bsdtar treat unrecognized types as 'File'
|
|
// it may be worth doing the same, but with a warning.
|
|
default:
|
|
this.ignore = true
|
|
}
|
|
|
|
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
|
|
|
|
if (ex) this[SLURP](ex)
|
|
if (gex) this[SLURP](gex, true)
|
|
}
|
|
|
|
write (data) {
|
|
const writeLen = data.length
|
|
if (writeLen > this.blockRemain)
|
|
throw new Error('writing more to entry than is appropriate')
|
|
|
|
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
|
|
|
|
if (r >= writeLen)
|
|
return super.write(data)
|
|
|
|
// r < writeLen
|
|
return super.write(data.slice(0, r))
|
|
}
|
|
|
|
[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]
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 287 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
// 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]]))
|
|
|
|
|
|
/***/ }),
|
|
/* 288 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
const Buffer = __webpack_require__(277)
|
|
const MiniPass = __webpack_require__(280)
|
|
const Pax = __webpack_require__(289)
|
|
const Header = __webpack_require__(290)
|
|
const ReadEntry = __webpack_require__(286)
|
|
const fs = __webpack_require__(55)
|
|
const path = __webpack_require__(57)
|
|
|
|
const types = __webpack_require__(287)
|
|
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__(292)
|
|
const winchars = __webpack_require__(293)
|
|
|
|
const modeFix = __webpack_require__(294)
|
|
|
|
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)
|
|
|
|
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)
|
|
}
|
|
|
|
this.win32 = !!opt.win32 || process.platform === 'win32'
|
|
if (this.win32) {
|
|
this.path = winchars.decode(this.path.replace(/\\/g, '/'))
|
|
p = p.replace(/\\/g, '/')
|
|
}
|
|
|
|
this.absolute = opt.absolute || path.resolve(this.cwd, p)
|
|
|
|
if (this.path === '')
|
|
this.path = './'
|
|
|
|
if (this.statCache.has(this.absolute))
|
|
this[ONLSTAT](this.statCache.get(this.absolute))
|
|
else
|
|
this[LSTAT]()
|
|
}
|
|
|
|
[LSTAT] () {
|
|
fs.lstat(this.absolute, (er, stat) => {
|
|
if (er)
|
|
return this.emit('error', er)
|
|
this[ONLSTAT](stat)
|
|
})
|
|
}
|
|
|
|
[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]()
|
|
}
|
|
|
|
[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()
|
|
}
|
|
}
|
|
|
|
[MODE] (mode) {
|
|
return modeFix(mode, this.type === 'Directory')
|
|
}
|
|
|
|
[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
|
|
})
|
|
|
|
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)
|
|
}
|
|
|
|
[DIRECTORY] () {
|
|
if (this.path.substr(-1) !== '/')
|
|
this.path += '/'
|
|
this.stat.size = 0
|
|
this[HEADER]()
|
|
this.end()
|
|
}
|
|
|
|
[SYMLINK] () {
|
|
fs.readlink(this.absolute, (er, linkpath) => {
|
|
if (er)
|
|
return this.emit('error', er)
|
|
this[ONREADLINK](linkpath)
|
|
})
|
|
}
|
|
|
|
[ONREADLINK] (linkpath) {
|
|
this.linkpath = linkpath
|
|
this[HEADER]()
|
|
this.end()
|
|
}
|
|
|
|
[HARDLINK] (linkpath) {
|
|
this.type = 'Link'
|
|
this.linkpath = path.relative(this.cwd, linkpath)
|
|
this.stat.size = 0
|
|
this[HEADER]()
|
|
this.end()
|
|
}
|
|
|
|
[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[HEADER]()
|
|
if (this.stat.size === 0)
|
|
return this.end()
|
|
|
|
this[OPENFILE]()
|
|
}
|
|
|
|
[OPENFILE] () {
|
|
fs.open(this.absolute, 'r', (er, fd) => {
|
|
if (er)
|
|
return this.emit('error', er)
|
|
this[ONOPENFILE](fd)
|
|
})
|
|
}
|
|
|
|
[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)
|
|
}
|
|
|
|
[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)
|
|
})
|
|
}
|
|
|
|
[CLOSE] (fd, cb) {
|
|
fs.close(fd, cb)
|
|
}
|
|
|
|
[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 (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)
|
|
}
|
|
|
|
// 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 ++
|
|
}
|
|
}
|
|
|
|
const writeBuf = offset === 0 && bytesRead === buf.length ?
|
|
buf : buf.slice(offset, offset + bytesRead)
|
|
remain -= bytesRead
|
|
blockRemain -= bytesRead
|
|
pos += bytesRead
|
|
offset += bytesRead
|
|
|
|
this.write(writeBuf)
|
|
|
|
if (!remain) {
|
|
if (blockRemain)
|
|
this.write(Buffer.alloc(blockRemain))
|
|
this.end()
|
|
this[CLOSE](fd, _ => _)
|
|
return
|
|
}
|
|
|
|
if (offset >= length) {
|
|
buf = Buffer.allocUnsafe(length)
|
|
offset = 0
|
|
}
|
|
length = buf.length - offset
|
|
this[READ](fd, buf, offset, length, pos, remain, blockRemain)
|
|
}
|
|
})
|
|
|
|
class WriteEntrySync extends WriteEntry {
|
|
constructor (path, opt) {
|
|
super(path, opt)
|
|
}
|
|
|
|
[LSTAT] () {
|
|
this[ONLSTAT](fs.lstatSync(this.absolute))
|
|
}
|
|
|
|
[SYMLINK] () {
|
|
this[ONREADLINK](fs.readlinkSync(this.absolute))
|
|
}
|
|
|
|
[OPENFILE] () {
|
|
this[ONOPENFILE](fs.openSync(this.absolute, 'r'))
|
|
}
|
|
|
|
[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) {}
|
|
}
|
|
}
|
|
|
|
[CLOSE] (fd) {
|
|
fs.closeSync(fd)
|
|
}
|
|
}
|
|
|
|
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
|
|
|
|
this.readEntry = readEntry
|
|
this.type = readEntry.type
|
|
if (this.type === 'Directory' && this.portable)
|
|
this.noMtime = true
|
|
|
|
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
|
|
|
|
if (typeof opt.onwarn === 'function')
|
|
this.on('warn', opt.onwarn)
|
|
|
|
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)
|
|
}
|
|
|
|
this.remain = readEntry.size
|
|
this.blockRemain = readEntry.startBlockSize
|
|
|
|
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 (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())
|
|
|
|
super.write(this.header.block)
|
|
readEntry.pipe(this)
|
|
}
|
|
|
|
[MODE] (mode) {
|
|
return modeFix(mode, this.type === 'Directory')
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
end () {
|
|
if (this.blockRemain)
|
|
this.write(Buffer.alloc(this.blockRemain))
|
|
return super.end()
|
|
}
|
|
})
|
|
|
|
WriteEntry.Sync = WriteEntrySync
|
|
WriteEntry.Tar = WriteEntryTar
|
|
|
|
const getType = stat =>
|
|
stat.isFile() ? 'File'
|
|
: stat.isDirectory() ? 'Directory'
|
|
: stat.isSymbolicLink() ? 'SymbolicLink'
|
|
: 'Unsupported'
|
|
|
|
module.exports = WriteEntry
|
|
|
|
|
|
/***/ }),
|
|
/* 289 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
const Buffer = __webpack_require__(277)
|
|
const Header = __webpack_require__(290)
|
|
const path = __webpack_require__(57)
|
|
|
|
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
|
|
}
|
|
|
|
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)
|
|
|
|
buf.write(body, 512, bodyLen, 'utf8')
|
|
|
|
// null pad after the body
|
|
for (let i = bodyLen + 512; i < buf.length; i++) {
|
|
buf[i] = 0
|
|
}
|
|
|
|
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')
|
|
)
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
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
|
|
|
|
|
|
/***/ }),
|
|
/* 290 */
|
|
/***/ (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__(277)
|
|
const types = __webpack_require__(287)
|
|
const pathModule = __webpack_require__(57).posix
|
|
const large = __webpack_require__(291)
|
|
|
|
const SLURP = Symbol('slurp')
|
|
const TYPE = Symbol('type')
|
|
|
|
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
|
|
|
|
if (Buffer.isBuffer(data))
|
|
this.decode(data, off || 0, ex, gex)
|
|
else if (data)
|
|
this.set(data)
|
|
}
|
|
|
|
decode (buf, off, ex, gex) {
|
|
if (!off)
|
|
off = 0
|
|
|
|
if (!buf || !(buf.length >= off + 512))
|
|
throw new Error('need 512 bytes for header')
|
|
|
|
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 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)
|
|
|
|
// 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'
|
|
|
|
// 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
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
[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]
|
|
}
|
|
}
|
|
|
|
encode (buf, off) {
|
|
if (!buf) {
|
|
buf = this.block = Buffer.alloc(512)
|
|
off = 0
|
|
}
|
|
|
|
if (!off)
|
|
off = 0
|
|
|
|
if (!(buf.length >= off + 512))
|
|
throw new Error('need 512 bytes for header')
|
|
|
|
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]
|
|
|
|
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
|
|
}
|
|
|
|
set (data) {
|
|
for (let i in data) {
|
|
if (data[i] !== null && data[i] !== undefined)
|
|
this[i] = data[i]
|
|
}
|
|
}
|
|
|
|
get type () {
|
|
return types.name.get(this[TYPE]) || this[TYPE]
|
|
}
|
|
|
|
get typeKey () {
|
|
return this[TYPE]
|
|
}
|
|
|
|
set type (type) {
|
|
if (types.code.has(type))
|
|
this[TYPE] = types.code.get(type)
|
|
else
|
|
this[TYPE] = type
|
|
}
|
|
}
|
|
|
|
const splitPrefix = (p, prefixSize) => {
|
|
const pathSize = 100
|
|
let pp = p
|
|
let prefix = ''
|
|
let ret
|
|
const root = pathModule.parse(p).root || '.'
|
|
|
|
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]
|
|
|
|
else {
|
|
// make path take a bit from prefix
|
|
pp = pathModule.join(pathModule.basename(prefix), pp)
|
|
prefix = pathModule.dirname(prefix)
|
|
}
|
|
} while (prefix !== root && !ret)
|
|
|
|
// at this point, found no resolution, just truncate
|
|
if (!ret)
|
|
ret = [p.substr(0, pathSize - 1), '', true]
|
|
}
|
|
return ret
|
|
}
|
|
|
|
const decString = (buf, off, size) =>
|
|
buf.slice(off, off + size).toString('utf8').replace(/\0.*/, '')
|
|
|
|
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
|
|
}
|
|
|
|
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')
|
|
|
|
const octalString = (number, size) =>
|
|
padOctal(Math.floor(number).toString(8), size)
|
|
|
|
const padOctal = (string, size) =>
|
|
(string.length === size - 1 ? string
|
|
: new Array(size - string.length - 1).join('0') + string + ' ') + '\0'
|
|
|
|
const encDate = (buf, off, size, date) =>
|
|
date === null ? false :
|
|
encNumber(buf, off, size, date.getTime() / 1000)
|
|
|
|
// 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)
|
|
|
|
module.exports = Header
|
|
|
|
|
|
/***/ }),
|
|
/* 291 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
// Tar can encode large and negative numbers using a leading byte of
|
|
// 0xff for negative, and 0x80 for positive.
|
|
|
|
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
|
|
}
|
|
|
|
const encodePositive = (num, buf) => {
|
|
buf[0] = 0x80
|
|
|
|
for (var i = buf.length; i > 1; i--) {
|
|
buf[i-1] = num & 0xff
|
|
num = Math.floor(num / 0x100)
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
|
|
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 (!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')
|
|
|
|
return 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)
|
|
}
|
|
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)
|
|
}
|
|
return sum
|
|
}
|
|
|
|
const onesComp = byte => (0xff ^ byte) & 0xff
|
|
|
|
const twosComp = byte => ((0xff ^ byte) + 1) & 0xff
|
|
|
|
|
|
/***/ }),
|
|
/* 292 */
|
|
/***/ (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)
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 293 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
// When writing files on Windows, translate the characters to their
|
|
// 0xf000 higher-encoded versions.
|
|
|
|
const raw = [
|
|
'|',
|
|
'<',
|
|
'>',
|
|
'?',
|
|
':'
|
|
]
|
|
|
|
const win = raw.map(char =>
|
|
String.fromCharCode(0xf000 + char.charCodeAt(0)))
|
|
|
|
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)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 294 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"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
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 295 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
const MiniPass = __webpack_require__(280)
|
|
const EE = __webpack_require__(49).EventEmitter
|
|
const fs = __webpack_require__(55)
|
|
|
|
// for writev
|
|
const binding = process.binding('fs')
|
|
const writeBuffers = binding.writeBuffers
|
|
const FSReqWrap = binding.FSReqWrap || binding.FSReqCallback
|
|
|
|
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')
|
|
|
|
class ReadStream extends MiniPass {
|
|
constructor (path, opt) {
|
|
opt = opt || {}
|
|
super(opt)
|
|
|
|
this.writable = false
|
|
|
|
if (typeof path !== 'string')
|
|
throw new TypeError('path must be a string')
|
|
|
|
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]()
|
|
}
|
|
|
|
get fd () { return this[_fd] }
|
|
get path () { return this[_path] }
|
|
|
|
write () {
|
|
throw new TypeError('this is a readable stream')
|
|
}
|
|
|
|
end () {
|
|
throw new TypeError('this is a readable stream')
|
|
}
|
|
|
|
[_open] () {
|
|
fs.open(this[_path], 'r', (er, fd) => this[_onopen](er, fd))
|
|
}
|
|
|
|
[_onopen] (er, fd) {
|
|
if (er)
|
|
this[_onerror](er)
|
|
else {
|
|
this[_fd] = fd
|
|
this.emit('open', fd)
|
|
this[_read]()
|
|
}
|
|
}
|
|
|
|
[_makeBuf] () {
|
|
return Buffer.allocUnsafe(Math.min(this[_readSize], this[_remain]))
|
|
}
|
|
|
|
[_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))
|
|
}
|
|
}
|
|
|
|
[_onread] (er, br, buf) {
|
|
this[_reading] = false
|
|
if (er)
|
|
this[_onerror](er)
|
|
else if (this[_handleChunk](br, buf))
|
|
this[_read]()
|
|
}
|
|
|
|
[_close] () {
|
|
if (this[_autoClose] && typeof this[_fd] === 'number') {
|
|
fs.close(this[_fd], _ => this.emit('close'))
|
|
this[_fd] = null
|
|
}
|
|
}
|
|
|
|
[_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 ReadStreamSync extends ReadStream {
|
|
[_open] () {
|
|
let threw = true
|
|
try {
|
|
this[_onopen](null, fs.openSync(this[_path], 'r'))
|
|
threw = false
|
|
} finally {
|
|
if (threw)
|
|
this[_close]()
|
|
}
|
|
}
|
|
|
|
[_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
|
|
}
|
|
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')
|
|
}
|
|
}
|
|
}
|
|
|
|
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]()
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
if (this[_fd] === null || this[_writing] || this[_queue].length) {
|
|
this[_queue].push(buf)
|
|
this[_needDrain] = true
|
|
return false
|
|
}
|
|
|
|
this[_writing] = true
|
|
this[_write](buf)
|
|
return true
|
|
}
|
|
|
|
[_write] (buf) {
|
|
fs.write(this[_fd], buf, 0, buf.length, this[_pos], (er, bw) =>
|
|
this[_onwrite](er, bw))
|
|
}
|
|
|
|
[_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')
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[_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))
|
|
}
|
|
}
|
|
|
|
[_close] () {
|
|
if (this[_autoClose] && typeof this[_fd] === 'number') {
|
|
fs.close(this[_fd], _ => this.emit('close'))
|
|
this[_fd] = null
|
|
}
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
[_close] () {
|
|
if (this[_autoClose] && typeof this[_fd] === 'number') {
|
|
try {
|
|
fs.closeSync(this[_fd])
|
|
} catch (er) {}
|
|
this[_fd] = null
|
|
this.emit('close')
|
|
}
|
|
}
|
|
|
|
[_write] (buf) {
|
|
try {
|
|
this[_onwrite](null,
|
|
fs.writeSync(this[_fd], buf, 0, buf.length, this[_pos]))
|
|
} catch (er) {
|
|
this[_onwrite](er, 0)
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
|
|
|
|
/***/ }),
|
|
/* 296 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const Buffer = __webpack_require__(277)
|
|
|
|
// XXX: This shares a lot in common with extract.js
|
|
// maybe some DRY opportunity here?
|
|
|
|
// tar -t
|
|
const hlo = __webpack_require__(275)
|
|
const Parser = __webpack_require__(297)
|
|
const fs = __webpack_require__(55)
|
|
const fsm = __webpack_require__(295)
|
|
const path = __webpack_require__(57)
|
|
|
|
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)
|
|
|
|
return opt.file && opt.sync ? listFileSync(opt)
|
|
: opt.file ? listFile(opt, cb)
|
|
: list(opt)
|
|
}
|
|
|
|
const onentryFunction = opt => {
|
|
const onentry = opt.onentry
|
|
opt.onentry = onentry ? e => {
|
|
onentry(e)
|
|
e.resume()
|
|
} : e => e.resume()
|
|
}
|
|
|
|
// 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 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 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)
|
|
|
|
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
|
|
}
|
|
|
|
const list = opt => new Parser(opt)
|
|
|
|
|
|
/***/ }),
|
|
/* 297 */
|
|
/***/ (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__(292)
|
|
const path = __webpack_require__(57)
|
|
const Header = __webpack_require__(290)
|
|
const EE = __webpack_require__(49)
|
|
const Yallist = __webpack_require__(281)
|
|
const maxMetaEntrySize = 1024 * 1024
|
|
const Entry = __webpack_require__(286)
|
|
const Pax = __webpack_require__(289)
|
|
const zlib = __webpack_require__(284)
|
|
const Buffer = __webpack_require__(277)
|
|
|
|
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 noop = _ => true
|
|
|
|
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')
|
|
})
|
|
|
|
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[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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[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
|
|
}
|
|
}
|
|
|
|
return go
|
|
}
|
|
|
|
[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'))
|
|
}
|
|
}
|
|
|
|
[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)
|
|
|
|
entry.write(c)
|
|
|
|
if (!entry.blockRemain) {
|
|
this[STATE] = 'begin'
|
|
this[WRITEENTRY] = null
|
|
entry.end()
|
|
}
|
|
|
|
return c.length
|
|
}
|
|
|
|
[CONSUMEMETA] (chunk, position) {
|
|
const entry = this[WRITEENTRY]
|
|
const ret = this[CONSUMEBODY](chunk, position)
|
|
|
|
// if we finished, then the entry is reset
|
|
if (!this[WRITEENTRY])
|
|
this[EMITMETA](entry)
|
|
|
|
return ret
|
|
}
|
|
|
|
[EMIT] (ev, data, extra) {
|
|
if (!this[QUEUE].length && !this[READENTRY])
|
|
this.emit(ev, data, extra)
|
|
else
|
|
this[QUEUE].push([ev, data, extra])
|
|
}
|
|
|
|
[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)
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
[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]()
|
|
}
|
|
|
|
[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])
|
|
}
|
|
}
|
|
|
|
if (position < length) {
|
|
if (this[BUFFER])
|
|
this[BUFFER] = Buffer.concat([chunk.slice(position), this[BUFFER]])
|
|
else
|
|
this[BUFFER] = chunk.slice(position)
|
|
}
|
|
}
|
|
|
|
end (chunk) {
|
|
if (!this[ABORTED]) {
|
|
if (this[UNZIP])
|
|
this[UNZIP].end(chunk)
|
|
else {
|
|
this[ENDED] = true
|
|
this.write(chunk)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
|
|
/***/ }),
|
|
/* 298 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
const Buffer = __webpack_require__(277)
|
|
|
|
// tar -r
|
|
const hlo = __webpack_require__(275)
|
|
const Pack = __webpack_require__(276)
|
|
const Parse = __webpack_require__(297)
|
|
const fs = __webpack_require__(55)
|
|
const fsm = __webpack_require__(295)
|
|
const t = __webpack_require__(296)
|
|
const path = __webpack_require__(57)
|
|
|
|
// 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.
|
|
|
|
const Header = __webpack_require__(290)
|
|
|
|
const r = module.exports = (opt_, files, cb) => {
|
|
const opt = hlo(opt_)
|
|
|
|
if (!opt.file)
|
|
throw new TypeError('file is required')
|
|
|
|
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)
|
|
|
|
return opt.sync ? replaceSync(opt, files)
|
|
: replace(opt, files, cb)
|
|
}
|
|
|
|
const replaceSync = (opt, files) => {
|
|
const p = new Pack.Sync(opt)
|
|
|
|
let threw = true
|
|
let fd
|
|
let position
|
|
|
|
try {
|
|
try {
|
|
fd = fs.openSync(opt.file, 'r+')
|
|
} catch (er) {
|
|
if (er.code === 'ENOENT')
|
|
fd = fs.openSync(opt.file, 'w+')
|
|
else
|
|
throw er
|
|
}
|
|
|
|
const st = fs.fstatSync(fd)
|
|
const headBuf = Buffer.alloc(512)
|
|
|
|
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 (position === 0 && headBuf[0] === 0x1f && headBuf[1] === 0x8b)
|
|
throw new Error('cannot append to compressed archives')
|
|
|
|
if (!bytes)
|
|
break POSITION
|
|
}
|
|
|
|
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
|
|
|
|
streamSync(opt, p, position, fd, files)
|
|
} finally {
|
|
if (threw)
|
|
try { fs.closeSync(fd) } catch (er) {}
|
|
}
|
|
}
|
|
|
|
const streamSync = (opt, p, position, fd, files) => {
|
|
const stream = new fsm.WriteStreamSync(opt.file, {
|
|
fd: fd,
|
|
start: position
|
|
})
|
|
p.pipe(stream)
|
|
addFilesSync(p, files)
|
|
}
|
|
|
|
const replace = (opt, files, cb) => {
|
|
files = Array.from(files)
|
|
const p = new Pack(opt)
|
|
|
|
const getPos = (fd, size, cb_) => {
|
|
const cb = (er, pos) => {
|
|
if (er)
|
|
fs.close(fd, _ => cb_(er))
|
|
else
|
|
cb_(null, pos)
|
|
}
|
|
|
|
let position = 0
|
|
if (size === 0)
|
|
return cb(null, 0)
|
|
|
|
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'))
|
|
|
|
// truncated header
|
|
if (bufPos < 512)
|
|
return cb(null, position)
|
|
|
|
const h = new Header(headBuf)
|
|
if (!h.cksumValid)
|
|
return cb(null, position)
|
|
|
|
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)
|
|
|
|
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)
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
if (er)
|
|
return reject(er)
|
|
|
|
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)
|
|
})
|
|
})
|
|
}
|
|
fs.open(opt.file, flag, onopen)
|
|
})
|
|
|
|
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()
|
|
}
|
|
|
|
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()
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 299 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
// tar -u
|
|
|
|
const hlo = __webpack_require__(275)
|
|
const r = __webpack_require__(298)
|
|
// just call tar.r with the filter and mtimeCache
|
|
|
|
const u = module.exports = (opt_, files, cb) => {
|
|
const opt = hlo(opt_)
|
|
|
|
if (!opt.file)
|
|
throw new TypeError('file is required')
|
|
|
|
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)
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 300 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
// tar -x
|
|
const hlo = __webpack_require__(275)
|
|
const Unpack = __webpack_require__(301)
|
|
const fs = __webpack_require__(55)
|
|
const fsm = __webpack_require__(295)
|
|
const path = __webpack_require__(57)
|
|
|
|
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 (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)
|
|
|
|
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)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 301 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const assert = __webpack_require__(101)
|
|
const EE = __webpack_require__(49).EventEmitter
|
|
const Parser = __webpack_require__(297)
|
|
const fs = __webpack_require__(55)
|
|
const fsm = __webpack_require__(295)
|
|
const path = __webpack_require__(57)
|
|
const mkdir = __webpack_require__(302)
|
|
const mkdirSync = mkdir.sync
|
|
const wc = __webpack_require__(293)
|
|
|
|
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__(159)
|
|
|
|
// 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)
|
|
}
|
|
|
|
// 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
|
|
|
|
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
|
|
}
|
|
|
|
// 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 ><?| in filenames into 0xf000-higher encoded forms
|
|
this.win32 = !!opt.win32 || process.platform === 'win32'
|
|
|
|
// do not unpack over files that are newer than what's in the archive
|
|
this.newer = !!opt.newer
|
|
|
|
// do not unpack over ANY files
|
|
this.keep = !!opt.keep
|
|
|
|
// do not set mtime/atime of extracted entries
|
|
this.noMtime = !!opt.noMtime
|
|
|
|
// allow .., absolute path entries, and unpacking through symlinks
|
|
// without this, warn and skip .., relativize absolutes, and error
|
|
// on symlinks in extraction path
|
|
this.preservePaths = !!opt.preservePaths
|
|
|
|
// unlink files and links before writing. This breaks existing hard
|
|
// links, and removes symlink directories rather than erroring
|
|
this.unlink = !!opt.unlink
|
|
|
|
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))
|
|
}
|
|
|
|
[MAYBECLOSE] () {
|
|
if (this[ENDED] && this[PENDING] === 0) {
|
|
this.emit('prefinish')
|
|
this.emit('finish')
|
|
this.emit('end')
|
|
this.emit('close')
|
|
}
|
|
}
|
|
|
|
[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('/')
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
// 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))
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
[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()
|
|
}
|
|
}
|
|
|
|
[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]())
|
|
}
|
|
|
|
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)
|
|
}
|
|
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()
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
[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)
|
|
}
|
|
}
|
|
|
|
[FILE] (entry) {
|
|
const mode = entry.mode & 0o7777 || this.fmode
|
|
|
|
const oner = er => {
|
|
try { fs.closeSync(fd) } catch (_) {}
|
|
if (er)
|
|
this[ONERROR](er, entry)
|
|
}
|
|
|
|
let stream
|
|
let fd
|
|
try {
|
|
fd = fs.openSync(entry.absolute, 'w', mode)
|
|
} catch (er) {
|
|
return oner(er)
|
|
}
|
|
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) {}
|
|
}
|
|
if (this[DOCHOWN](entry)) {
|
|
try {
|
|
fs.chownSync(entry.absolute, this[UID](entry), this[GID](entry))
|
|
} catch (er) {}
|
|
}
|
|
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
|
|
}
|
|
}
|
|
|
|
[LINK] (entry, linkpath, link) {
|
|
try {
|
|
fs[link + 'Sync'](linkpath, entry.absolute)
|
|
entry.resume()
|
|
} catch (er) {
|
|
return this[ONERROR](er, entry)
|
|
}
|
|
}
|
|
}
|
|
|
|
Unpack.Sync = UnpackSync
|
|
module.exports = Unpack
|
|
|
|
|
|
/***/ }),
|
|
/* 302 */
|
|
/***/ (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 mkdirp = __webpack_require__(179)
|
|
const fs = __webpack_require__(55)
|
|
const path = __webpack_require__(57)
|
|
const chownr = __webpack_require__(303)
|
|
|
|
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()
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
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)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 303 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
const fs = __webpack_require__(55)
|
|
const path = __webpack_require__(57)
|
|
|
|
/* 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
|
|
|
|
|
|
/***/ }),
|
|
/* 304 */
|
|
/***/ (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__(266);
|
|
const tunnel_1 = tslib_1.__importDefault(__webpack_require__(305));
|
|
const url_1 = __webpack_require__(264);
|
|
const zlib_1 = tslib_1.__importDefault(__webpack_require__(137));
|
|
const is_1 = __webpack_require__(191);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('model-fetch');
|
|
function getAgent(endpoint) {
|
|
let proxy = workspace_1.default.getConfiguration('http').get('proxy', '');
|
|
let key = endpoint.protocol.startsWith('https') ? 'HTTPS_PROXY' : 'HTTP_PROXY';
|
|
let env = process.env[key];
|
|
if (!proxy && env && env.startsWith('http')) {
|
|
proxy = env.replace(/^https?:\/\//, '').replace(/\/$/, '');
|
|
}
|
|
const noProxy = process.env.NO_PROXY || process.env.no_proxy || null;
|
|
if (noProxy === '*') {
|
|
proxy = null;
|
|
}
|
|
else if (noProxy !== null) {
|
|
// 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)) {
|
|
proxy = null;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
noProxyItem = noProxyItem.replace(/^\.*/, '.');
|
|
if (hostname.endsWith(noProxyItem)) {
|
|
proxy = null;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (proxy) {
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
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';
|
|
}
|
|
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);
|
|
}
|
|
});
|
|
});
|
|
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
|
|
|
|
/***/ }),
|
|
/* 305 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
module.exports = __webpack_require__(306);
|
|
|
|
|
|
/***/ }),
|
|
/* 306 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var net = __webpack_require__(6);
|
|
var tls = __webpack_require__(307);
|
|
var http = __webpack_require__(267);
|
|
var https = __webpack_require__(268);
|
|
var events = __webpack_require__(49);
|
|
var assert = __webpack_require__(101);
|
|
var util = __webpack_require__(40);
|
|
|
|
|
|
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;
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
|
|
function onCloseOrRemove(err) {
|
|
self.removeSocket(socket);
|
|
socket.removeListener('free', onFree);
|
|
socket.removeListener('close', onCloseOrRemove);
|
|
socket.removeListener('agentRemove', onCloseOrRemove);
|
|
}
|
|
});
|
|
};
|
|
|
|
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
|
|
}
|
|
});
|
|
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;
|
|
}
|
|
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];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return target;
|
|
}
|
|
|
|
|
|
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() {};
|
|
}
|
|
exports.debug = debug; // for test
|
|
|
|
|
|
/***/ }),
|
|
/* 307 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("tls");
|
|
|
|
/***/ }),
|
|
/* 308 */
|
|
/***/ (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__(55));
|
|
const object_1 = __webpack_require__(190);
|
|
const logger = __webpack_require__(186)('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
|
|
|
|
/***/ }),
|
|
/* 309 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
const logger = __webpack_require__(186)('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
|
|
|
|
/***/ }),
|
|
/* 310 */
|
|
/***/ (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__(55));
|
|
const path = tslib_1.__importStar(__webpack_require__(57));
|
|
const vm = tslib_1.__importStar(__webpack_require__(311));
|
|
const lodash_1 = __webpack_require__(312);
|
|
const createLogger = __webpack_require__(186);
|
|
const logger = createLogger('util-factoroy');
|
|
const requireFunc = true ? require : undefined;
|
|
const Module = __webpack_require__(313);
|
|
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__(314);
|
|
}
|
|
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: {
|
|
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
|
|
};
|
|
}
|
|
exports.createExtension = createExtension;
|
|
//# sourceMappingURL=factory.js.map
|
|
|
|
/***/ }),
|
|
/* 311 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("vm");
|
|
|
|
/***/ }),
|
|
/* 312 */
|
|
/***/ (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
|
|
|
|
/***/ }),
|
|
/* 313 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("module");
|
|
|
|
/***/ }),
|
|
/* 314 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const commands_1 = tslib_1.__importDefault(__webpack_require__(232));
|
|
exports.commands = commands_1.default;
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
exports.events = events_1.default;
|
|
const languages_1 = tslib_1.__importDefault(__webpack_require__(315));
|
|
exports.languages = languages_1.default;
|
|
const document_1 = tslib_1.__importDefault(__webpack_require__(207));
|
|
exports.Document = document_1.default;
|
|
const mru_1 = tslib_1.__importDefault(__webpack_require__(215));
|
|
exports.Mru = mru_1.default;
|
|
const floatBuffer_1 = tslib_1.__importDefault(__webpack_require__(318));
|
|
exports.FloatBuffer = floatBuffer_1.default;
|
|
const floatFactory_1 = tslib_1.__importDefault(__webpack_require__(317));
|
|
exports.FloatFactory = floatFactory_1.default;
|
|
const fetch_1 = tslib_1.__importDefault(__webpack_require__(304));
|
|
exports.fetch = fetch_1.default;
|
|
const download_1 = tslib_1.__importDefault(__webpack_require__(265));
|
|
exports.download = download_1.default;
|
|
const highligher_1 = tslib_1.__importDefault(__webpack_require__(349));
|
|
exports.Highligher = highligher_1.default;
|
|
const fileSystemWatcher_1 = tslib_1.__importDefault(__webpack_require__(214));
|
|
exports.FileSystemWatcher = fileSystemWatcher_1.default;
|
|
const services_1 = tslib_1.__importDefault(__webpack_require__(351));
|
|
exports.services = services_1.default;
|
|
const sources_1 = tslib_1.__importDefault(__webpack_require__(237));
|
|
exports.sources = sources_1.default;
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
exports.workspace = workspace_1.default;
|
|
const extensions_1 = tslib_1.__importDefault(__webpack_require__(238));
|
|
exports.extensions = extensions_1.default;
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(364));
|
|
exports.listManager = manager_1.default;
|
|
const manager_2 = tslib_1.__importDefault(__webpack_require__(233));
|
|
exports.snippetManager = manager_2.default;
|
|
const basic_1 = tslib_1.__importDefault(__webpack_require__(371));
|
|
exports.BasicList = basic_1.default;
|
|
const manager_3 = tslib_1.__importDefault(__webpack_require__(316));
|
|
exports.diagnosticManager = manager_3.default;
|
|
const ansiparse_1 = __webpack_require__(350);
|
|
exports.ansiparse = ansiparse_1.ansiparse;
|
|
const watchman_1 = tslib_1.__importDefault(__webpack_require__(227));
|
|
exports.Watchman = watchman_1.default;
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
exports.Uri = vscode_uri_1.URI;
|
|
const neovim_1 = __webpack_require__(4);
|
|
exports.Neovim = neovim_1.Neovim;
|
|
exports.Buffer = neovim_1.Buffer;
|
|
exports.Window = neovim_1.Window;
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
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__(189), exports);
|
|
tslib_1.__exportStar(__webpack_require__(352), exports);
|
|
var util_1 = __webpack_require__(174);
|
|
exports.disposeAll = util_1.disposeAll;
|
|
exports.runCommand = util_1.runCommand;
|
|
exports.isRunning = util_1.isRunning;
|
|
exports.executable = util_1.executable;
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
/* 315 */
|
|
/***/ (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__(149);
|
|
const commands_1 = tslib_1.__importDefault(__webpack_require__(232));
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(316));
|
|
const codeActionmanager_1 = tslib_1.__importDefault(__webpack_require__(327));
|
|
const codeLensManager_1 = tslib_1.__importDefault(__webpack_require__(329));
|
|
const declarationManager_1 = tslib_1.__importDefault(__webpack_require__(330));
|
|
const definitionManager_1 = tslib_1.__importDefault(__webpack_require__(331));
|
|
const documentColorManager_1 = tslib_1.__importDefault(__webpack_require__(332));
|
|
const documentHighlightManager_1 = tslib_1.__importDefault(__webpack_require__(333));
|
|
const documentLinkManager_1 = tslib_1.__importDefault(__webpack_require__(334));
|
|
const documentSymbolManager_1 = tslib_1.__importDefault(__webpack_require__(335));
|
|
const foldingRangeManager_1 = tslib_1.__importDefault(__webpack_require__(336));
|
|
const formatManager_1 = tslib_1.__importDefault(__webpack_require__(337));
|
|
const formatRangeManager_1 = tslib_1.__importDefault(__webpack_require__(338));
|
|
const hoverManager_1 = tslib_1.__importDefault(__webpack_require__(339));
|
|
const implementationManager_1 = tslib_1.__importDefault(__webpack_require__(340));
|
|
const onTypeFormatManager_1 = tslib_1.__importDefault(__webpack_require__(341));
|
|
const rangeManager_1 = tslib_1.__importDefault(__webpack_require__(342));
|
|
const referenceManager_1 = tslib_1.__importDefault(__webpack_require__(343));
|
|
const renameManager_1 = tslib_1.__importDefault(__webpack_require__(344));
|
|
const signatureManager_1 = tslib_1.__importDefault(__webpack_require__(345));
|
|
const typeDefinitionManager_1 = tslib_1.__importDefault(__webpack_require__(346));
|
|
const workspaceSymbolsManager_1 = tslib_1.__importDefault(__webpack_require__(347));
|
|
const manager_2 = tslib_1.__importDefault(__webpack_require__(233));
|
|
const sources_1 = tslib_1.__importDefault(__webpack_require__(237));
|
|
const types_1 = __webpack_require__(189);
|
|
const util_1 = __webpack_require__(174);
|
|
const complete = tslib_1.__importStar(__webpack_require__(348));
|
|
const position_1 = __webpack_require__(213);
|
|
const string_1 = __webpack_require__(210);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('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 = [], priority) {
|
|
languageIds = typeof languageIds == 'string' ? [languageIds] : languageIds;
|
|
let source = this.createCompleteSource(name, shortcut, provider, languageIds, triggerCharacters, 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<CodeAction[]>}
|
|
*/
|
|
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, 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;
|
|
if (commitCharacters && commitCharacters.indexOf(character) !== -1) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
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();
|
|
// tslint:disable-next-line:deprecation
|
|
if (isSnippet && item.insertText && item.insertText.indexOf('$') == -1 && !hasAdditionalEdit) {
|
|
// fix wrong insert format
|
|
isSnippet = false;
|
|
item.insertTextFormat = vscode_languageserver_protocol_1.InsertTextFormat.PlainText;
|
|
}
|
|
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,
|
|
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;
|
|
}
|
|
}
|
|
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
|
|
|
|
/***/ }),
|
|
/* 316 */
|
|
/***/ (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__(149);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const floatFactory_1 = tslib_1.__importDefault(__webpack_require__(317));
|
|
const util_1 = __webpack_require__(174);
|
|
const position_1 = __webpack_require__(213);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const buffer_1 = __webpack_require__(323);
|
|
const collection_1 = tslib_1.__importDefault(__webpack_require__(326));
|
|
const util_2 = __webpack_require__(325);
|
|
const logger = __webpack_require__(186)('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();
|
|
nvim.command(`sign define CocError text=${errorSign} linehl=CocErrorLine texthl=CocErrorSign`, true);
|
|
nvim.command(`sign define CocWarning text=${warningSign} linehl=CocWarningLine texthl=CocWarningSign`, true);
|
|
nvim.command(`sign define CocInfo text=${infoSign} linehl=CocInfoLine texthl=CocInfoSign`, true);
|
|
nvim.command(`sign define CocHint text=${hintSign} linehl=CocHintLine texthl=CocHintSign`, 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);
|
|
collection.onDidDiagnosticsChange(async (uri) => {
|
|
if (this.config.refreshAfterSave)
|
|
return;
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
/**
|
|
* Jump to previouse 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;
|
|
}
|
|
}
|
|
await workspace_1.default.moveTo(ranges[ranges.length - 1].start);
|
|
}
|
|
/**
|
|
* 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;
|
|
}
|
|
}
|
|
await workspace_1.default.moveTo(ranges[0].start);
|
|
}
|
|
/**
|
|
* 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;
|
|
}
|
|
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 => {
|
|
if (checkCurrentLine)
|
|
return position_1.lineInRange(pos.line, o.range);
|
|
return position_1.positionInRange(pos, o.range) == 0;
|
|
});
|
|
diagnostics.sort((a, b) => a.severity - b.severity);
|
|
return diagnostics;
|
|
}
|
|
async getCurrentDiagnostics() {
|
|
let [bufnr, cursor] = await this.nvim.eval('[bufnr("%"),coc#util#cursor()]');
|
|
return await this.getDiagnosticsAt(bufnr, cursor);
|
|
}
|
|
/**
|
|
* 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];
|
|
let str = `[${source}${code ? ' ' + code : ''}] [${s}] ${message}`;
|
|
let filetype = 'Error';
|
|
if (ft === '') {
|
|
switch (diagnostic.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);
|
|
}
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
buf.clear().logError();
|
|
}
|
|
hideFloat() {
|
|
if (this.floatFactory) {
|
|
this.floatFactory.close();
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
get nvim() {
|
|
return workspace_1.default.nvim;
|
|
}
|
|
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),
|
|
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', {}),
|
|
};
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
getCollections(uri) {
|
|
return this.collections.filter(c => c.has(uri));
|
|
}
|
|
shouldValidate(doc) {
|
|
return doc != null && doc.buftype == '';
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
exports.DiagnosticManager = DiagnosticManager;
|
|
exports.default = new DiagnosticManager();
|
|
//# sourceMappingURL=manager.js.map
|
|
|
|
/***/ }),
|
|
/* 317 */
|
|
/***/ (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__(149);
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(233));
|
|
const util_1 = __webpack_require__(174);
|
|
const object_1 = __webpack_require__(190);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const floatBuffer_1 = tslib_1.__importDefault(__webpack_require__(318));
|
|
const debounce_1 = tslib_1.__importDefault(__webpack_require__(176));
|
|
const popup_1 = tslib_1.__importDefault(__webpack_require__(322));
|
|
const array_1 = __webpack_require__(212);
|
|
const logger = __webpack_require__(186)('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 (!env.floating && !env.textprop)
|
|
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);
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
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);
|
|
win.setOption('showbreak', '', 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));
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
get columns() {
|
|
return this.env.columns;
|
|
}
|
|
get lines() {
|
|
return this.env.lines - this.env.cmdheight - 1;
|
|
}
|
|
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;
|
|
if (offsetX) {
|
|
offsetX = Math.min(col - 1, offsetX);
|
|
if (col - offsetX + width > columns) {
|
|
offsetX = col - offsetX + width - 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'
|
|
};
|
|
}
|
|
async create(docs, allowSelection = false, offsetX = 0) {
|
|
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("\\<C-g>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`, 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: config.height,
|
|
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;
|
|
}
|
|
checkMode(mode, allowSelection) {
|
|
if (mode == 's' && allowSelection) {
|
|
return true;
|
|
}
|
|
return ['i', 'n', 'ic'].indexOf(mode) != -1;
|
|
}
|
|
/**
|
|
* 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);
|
|
}
|
|
}
|
|
dispose() {
|
|
if (this.tokenSource) {
|
|
this.tokenSource.cancel();
|
|
}
|
|
util_1.disposeAll(this.disposables);
|
|
}
|
|
get buffer() {
|
|
return this.floatBuffer ? this.floatBuffer.buffer : null;
|
|
}
|
|
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.default = FloatFactory;
|
|
function cursorPostion(n) {
|
|
if (n == 0)
|
|
return 'cursor';
|
|
if (n < 0)
|
|
return `cursor${n}`;
|
|
return `cursor+${n}`;
|
|
}
|
|
//# sourceMappingURL=floatFactory.js.map
|
|
|
|
/***/ }),
|
|
/* 318 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const highlight_1 = __webpack_require__(319);
|
|
const string_1 = __webpack_require__(210);
|
|
const array_1 = __webpack_require__(212);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('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.tabstop = 2;
|
|
this.width = 0;
|
|
let config = workspace_1.default.getConfiguration('coc.preferences');
|
|
this.enableHighlight = config.get('enableFloatHighlight', true);
|
|
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).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;
|
|
if (this.window) {
|
|
nvim.call('win_execute', [this.window.id, 'call clearmatches([])'], true);
|
|
}
|
|
else {
|
|
nvim.call('clearmatches', [], 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 = FloatBuffer;
|
|
//# sourceMappingURL=floatBuffer.js.map
|
|
|
|
/***/ }),
|
|
/* 319 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const neovim_1 = __webpack_require__(4);
|
|
const cp = tslib_1.__importStar(__webpack_require__(175));
|
|
const crypto_1 = __webpack_require__(159);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const lodash_1 = __webpack_require__(312);
|
|
const os_1 = tslib_1.__importDefault(__webpack_require__(56));
|
|
const fs_1 = tslib_1.__importDefault(__webpack_require__(55));
|
|
const string_1 = __webpack_require__(210);
|
|
const processes_1 = __webpack_require__(320);
|
|
const uuid = __webpack_require__(321);
|
|
const logger = __webpack_require__(186)('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) {
|
|
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([]);
|
|
}, 500);
|
|
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', [`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
|
|
|
|
/***/ }),
|
|
/* 320 */
|
|
/***/ (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__(175));
|
|
const path_1 = __webpack_require__(57);
|
|
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 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 {
|
|
process.kill('SIGKILL');
|
|
return true;
|
|
}
|
|
}
|
|
exports.terminate = terminate;
|
|
//# sourceMappingURL=processes.js.map
|
|
|
|
/***/ }),
|
|
/* 321 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var rng = __webpack_require__(221);
|
|
var bytesToUuid = __webpack_require__(222);
|
|
|
|
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;
|
|
|
|
|
|
/***/ }),
|
|
/* 322 */
|
|
/***/ (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
|
|
|
|
/***/ }),
|
|
/* 323 */
|
|
/***/ (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__(149);
|
|
const callSequence_1 = tslib_1.__importDefault(__webpack_require__(324));
|
|
const object_1 = __webpack_require__(190);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const util_1 = __webpack_require__(325);
|
|
const logger = __webpack_require__(186)('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 false;
|
|
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)
|
|
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.command('redraws', true);
|
|
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 (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<void>}
|
|
*/
|
|
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
|
|
|
|
/***/ }),
|
|
/* 324 */
|
|
/***/ (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);
|
|
}
|
|
}
|
|
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
|
|
|
|
/***/ }),
|
|
/* 325 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
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
|
|
|
|
/***/ }),
|
|
/* 326 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const position_1 = __webpack_require__(213);
|
|
const logger = __webpack_require__(186)('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 => {
|
|
if (position_1.emptyRange(o.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
|
|
|
|
/***/ }),
|
|
/* 327 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
const logger = __webpack_require__(186)('codeActionManager');
|
|
class CodeActionManager extends manager_1.default {
|
|
register(selector, provider, clientId, codeActionKinds) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider,
|
|
kinds: codeActionKinds,
|
|
clientId
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideCodeActions(document, range, context, token) {
|
|
let providers = this.getProviders(document);
|
|
if (!providers.length)
|
|
return null;
|
|
if (context.only) {
|
|
let { only } = context;
|
|
providers = providers.filter(p => {
|
|
if (p.kinds && !p.kinds.some(kind => only.indexOf(kind) != -1)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
}
|
|
let res = new Map();
|
|
await Promise.all(providers.map(item => {
|
|
let { provider, clientId } = item;
|
|
clientId = clientId || uuid();
|
|
return Promise.resolve(provider.provideCodeActions(document, range, context, token)).then(actions => {
|
|
if (!actions || actions.length == 0)
|
|
return;
|
|
let codeActions = res.get(clientId) || [];
|
|
for (let action of actions) {
|
|
if (vscode_languageserver_protocol_1.Command.is(action)) {
|
|
codeActions.push(vscode_languageserver_protocol_1.CodeAction.create(action.title, action));
|
|
}
|
|
else {
|
|
if (context.only) {
|
|
if (!action.kind || context.only.indexOf(action.kind) == -1) {
|
|
continue;
|
|
}
|
|
}
|
|
let idx = codeActions.findIndex(o => o.title == action.title);
|
|
if (idx == -1)
|
|
codeActions.push(action);
|
|
}
|
|
}
|
|
res.set(clientId, codeActions);
|
|
});
|
|
}));
|
|
return res;
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = CodeActionManager;
|
|
//# sourceMappingURL=codeActionmanager.js.map
|
|
|
|
/***/ }),
|
|
/* 328 */
|
|
/***/ (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__(149);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('provider-manager');
|
|
class Manager {
|
|
constructor() {
|
|
this.providers = new Set();
|
|
}
|
|
hasProvider(document) {
|
|
return this.getProvider(document) != null;
|
|
}
|
|
getProvider(document) {
|
|
let currScore = 0;
|
|
let providerItem;
|
|
for (let item of this.providers) {
|
|
let { selector, priority } = item;
|
|
let score = workspace_1.default.match(selector, document);
|
|
if (score == 0)
|
|
continue;
|
|
if (typeof priority == 'number') {
|
|
score = priority;
|
|
}
|
|
if (score < currScore)
|
|
continue;
|
|
currScore = score;
|
|
providerItem = item;
|
|
}
|
|
return providerItem;
|
|
}
|
|
poviderById(id) {
|
|
let item = Array.from(this.providers).find(o => o.id == id);
|
|
return item ? item.provider : null;
|
|
}
|
|
getProviders(document) {
|
|
let items = Array.from(this.providers);
|
|
items = items.filter(item => {
|
|
return workspace_1.default.match(item.selector, document) > 0;
|
|
});
|
|
return items.sort((a, b) => {
|
|
return workspace_1.default.match(b.selector, document) - workspace_1.default.match(a.selector, document);
|
|
});
|
|
}
|
|
mergeDefinitions(arr) {
|
|
let res = [];
|
|
for (let def of arr) {
|
|
if (!def)
|
|
continue;
|
|
if (vscode_languageserver_protocol_1.Location.is(def)) {
|
|
let { uri, range } = def;
|
|
let idx = res.findIndex(l => l.uri == uri && l.range.start.line == range.start.line);
|
|
if (idx == -1) {
|
|
res.push(def);
|
|
}
|
|
}
|
|
else if (Array.isArray(def)) {
|
|
for (let d of def) {
|
|
let { uri, range } = d;
|
|
let idx = res.findIndex(l => l.uri == uri && l.range.start.line == range.start.line);
|
|
if (idx == -1) {
|
|
res.push(d);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
workspace_1.default.showMessage(`Bad definition ${JSON.stringify(def)}`, 'error');
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
}
|
|
exports.default = Manager;
|
|
//# sourceMappingURL=manager.js.map
|
|
|
|
/***/ }),
|
|
/* 329 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
const lodash_1 = __webpack_require__(312);
|
|
// const logger = require('../util/logger')('codeActionManager')
|
|
class CodeLensManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideCodeLenses(document, token) {
|
|
let providers = this.getProviders(document);
|
|
if (!providers.length)
|
|
return null;
|
|
let arr = await Promise.all(providers.map(item => {
|
|
let { provider, id } = item;
|
|
return Promise.resolve(provider.provideCodeLenses(document, token)).then(res => {
|
|
if (Array.isArray(res)) {
|
|
for (let item of res) {
|
|
item.source = id;
|
|
}
|
|
}
|
|
return res || [];
|
|
});
|
|
}));
|
|
return [].concat(...arr);
|
|
}
|
|
async resolveCodeLens(codeLens, token) {
|
|
// no need to resolve
|
|
if (codeLens.command)
|
|
return codeLens;
|
|
let { source } = codeLens;
|
|
let provider = this.poviderById(source);
|
|
if (!provider || typeof provider.resolveCodeLens != 'function') {
|
|
// tslint:disable-next-line:no-console
|
|
console.error(`CodeLens Resolve not supported`);
|
|
return codeLens;
|
|
}
|
|
let res = await Promise.resolve(provider.resolveCodeLens(lodash_1.omit(codeLens, ['source']), token));
|
|
Object.assign(codeLens, res);
|
|
return codeLens;
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = CodeLensManager;
|
|
//# sourceMappingURL=codeLensManager.js.map
|
|
|
|
/***/ }),
|
|
/* 330 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
const logger = __webpack_require__(186)('definitionManager');
|
|
class DeclarationManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideDeclaration(document, position, token) {
|
|
let item = this.getProvider(document);
|
|
if (!item)
|
|
return null;
|
|
let { provider } = item;
|
|
return await Promise.resolve(provider.provideDeclaration(document, position, token));
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = DeclarationManager;
|
|
//# sourceMappingURL=declarationManager.js.map
|
|
|
|
/***/ }),
|
|
/* 331 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
const logger = __webpack_require__(186)('definitionManager');
|
|
class DefinitionManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideDefinition(document, position, token) {
|
|
let providers = this.getProviders(document);
|
|
if (!providers.length)
|
|
return null;
|
|
let arr = await Promise.all(providers.map(item => {
|
|
let { provider } = item;
|
|
return Promise.resolve(provider.provideDefinition(document, position, token));
|
|
}));
|
|
return this.mergeDefinitions(arr);
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = DefinitionManager;
|
|
//# sourceMappingURL=definitionManager.js.map
|
|
|
|
/***/ }),
|
|
/* 332 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class DocumentColorManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideDocumentColors(document, token) {
|
|
let item = this.getProvider(document);
|
|
if (!item)
|
|
return null;
|
|
let { provider } = item;
|
|
let res = await Promise.resolve(provider.provideDocumentColors(document, token));
|
|
return res;
|
|
}
|
|
async provideColorPresentations(colorInformation, document, token) {
|
|
let { range, color } = colorInformation;
|
|
let item = this.getProvider(document);
|
|
if (!item)
|
|
return null;
|
|
let { provider } = item;
|
|
let res = await Promise.resolve(provider.provideColorPresentations(color, { document, range }, token));
|
|
return res;
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = DocumentColorManager;
|
|
//# sourceMappingURL=documentColorManager.js.map
|
|
|
|
/***/ }),
|
|
/* 333 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class DocumentHighlightManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideDocumentHighlights(document, position, token) {
|
|
let item = this.getProvider(document);
|
|
if (!item)
|
|
return null;
|
|
let { provider } = item;
|
|
return await Promise.resolve(provider.provideDocumentHighlights(document, position, token));
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = DocumentHighlightManager;
|
|
//# sourceMappingURL=documentHighlightManager.js.map
|
|
|
|
/***/ }),
|
|
/* 334 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class DocumentLinkManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async _provideDocumentLinks(item, document, token) {
|
|
let { provider, id } = item;
|
|
let items = await Promise.resolve(provider.provideDocumentLinks(document, token));
|
|
if (!items || !items.length)
|
|
return [];
|
|
items.forEach(item => {
|
|
item.data = item.data || {};
|
|
item.data.source = id;
|
|
});
|
|
return items;
|
|
}
|
|
async provideDocumentLinks(document, token) {
|
|
let items = this.getProviders(document);
|
|
if (items.length == 0)
|
|
return [];
|
|
const arr = await Promise.all(items.map(item => {
|
|
return this._provideDocumentLinks(item, document, token);
|
|
}));
|
|
return [].concat(...arr);
|
|
}
|
|
async resolveDocumentLink(link, token) {
|
|
let { data } = link;
|
|
if (!data || !data.source)
|
|
return null;
|
|
for (let item of this.providers) {
|
|
if (item.id == data.source) {
|
|
let { provider } = item;
|
|
link = await Promise.resolve(provider.resolveDocumentLink(link, token));
|
|
return link;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = DocumentLinkManager;
|
|
//# sourceMappingURL=documentLinkManager.js.map
|
|
|
|
/***/ }),
|
|
/* 335 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class DocumentSymbolManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideDocumentSymbols(document, token) {
|
|
let item = this.getProvider(document);
|
|
if (!item)
|
|
return null;
|
|
let { provider } = item;
|
|
return (await Promise.resolve(provider.provideDocumentSymbols(document, token))) || [];
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = DocumentSymbolManager;
|
|
//# sourceMappingURL=documentSymbolManager.js.map
|
|
|
|
/***/ }),
|
|
/* 336 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class FoldingRangeManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideFoldingRanges(document, context, token) {
|
|
let item = this.getProvider(document);
|
|
if (!item)
|
|
return null;
|
|
let { provider } = item;
|
|
return (await Promise.resolve(provider.provideFoldingRanges(document, context, token)) || []);
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = FoldingRangeManager;
|
|
//# sourceMappingURL=foldingRangeManager.js.map
|
|
|
|
/***/ }),
|
|
/* 337 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class FormatManager extends manager_1.default {
|
|
register(selector, provider, priority = 0) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
priority,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideDocumentFormattingEdits(document, options, token) {
|
|
let item = this.getProvider(document);
|
|
if (!item)
|
|
return null;
|
|
let { provider } = item;
|
|
return await Promise.resolve(provider.provideDocumentFormattingEdits(document, options, token));
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = FormatManager;
|
|
//# sourceMappingURL=formatManager.js.map
|
|
|
|
/***/ }),
|
|
/* 338 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class FormatRangeManager extends manager_1.default {
|
|
register(selector, provider, priority = 0) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider,
|
|
priority
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideDocumentRangeFormattingEdits(document, range, options, token) {
|
|
let item = this.getProvider(document);
|
|
if (!item)
|
|
return null;
|
|
let { provider } = item;
|
|
return await Promise.resolve(provider.provideDocumentRangeFormattingEdits(document, range, options, token));
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = FormatRangeManager;
|
|
//# sourceMappingURL=formatRangeManager.js.map
|
|
|
|
/***/ }),
|
|
/* 339 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class HoverManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideHover(document, position, token) {
|
|
let items = this.getProviders(document);
|
|
if (items.length === 0)
|
|
return null;
|
|
let res = [];
|
|
for (let i = 0, len = items.length; i < len; i += 1) {
|
|
const item = items[i];
|
|
let hover = await Promise.resolve(item.provider.provideHover(document, position, token));
|
|
if (hover && hover.contents != '')
|
|
res.push(hover);
|
|
}
|
|
return res;
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = HoverManager;
|
|
//# sourceMappingURL=hoverManager.js.map
|
|
|
|
/***/ }),
|
|
/* 340 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class ImplementationManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideReferences(document, position, token) {
|
|
let providers = this.getProviders(document);
|
|
if (!providers.length)
|
|
return null;
|
|
let arr = await Promise.all(providers.map(item => {
|
|
let { provider } = item;
|
|
return Promise.resolve(provider.provideImplementation(document, position, token));
|
|
}));
|
|
return this.mergeDefinitions(arr);
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = ImplementationManager;
|
|
//# sourceMappingURL=implementationManager.js.map
|
|
|
|
/***/ }),
|
|
/* 341 */
|
|
/***/ (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__(149);
|
|
const string_1 = __webpack_require__(210);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('onTypeFormatManager');
|
|
class OnTypeFormatManager {
|
|
constructor() {
|
|
this.providers = new Set();
|
|
}
|
|
register(selector, provider, triggerCharacters) {
|
|
let item = {
|
|
triggerCharacters,
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
hasProvider(document) {
|
|
for (let o of this.providers) {
|
|
let { selector } = o;
|
|
if (workspace_1.default.match(selector, document) > 0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
getProvider(document, triggerCharacter) {
|
|
for (let o of this.providers) {
|
|
let { triggerCharacters, selector } = o;
|
|
if (workspace_1.default.match(selector, document) > 0 && triggerCharacters.indexOf(triggerCharacter) > -1) {
|
|
return o.provider;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
async onCharacterType(character, document, position, token) {
|
|
if (string_1.isWord(character))
|
|
return;
|
|
let provider = this.getProvider(document, character);
|
|
if (!provider)
|
|
return;
|
|
let formatOpts = await workspace_1.default.getFormatOptions(document.uri);
|
|
return await Promise.resolve(provider.provideOnTypeFormattingEdits(document, position, character, formatOpts, token));
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = OnTypeFormatManager;
|
|
//# sourceMappingURL=onTypeFormatManager.js.map
|
|
|
|
/***/ }),
|
|
/* 342 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class SelectionRangeManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideSelectionRanges(document, positions, token) {
|
|
let item = this.getProvider(document);
|
|
if (!item)
|
|
return null;
|
|
let { provider } = item;
|
|
return (await Promise.resolve(provider.provideSelectionRanges(document, positions, token)) || []);
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = SelectionRangeManager;
|
|
//# sourceMappingURL=rangeManager.js.map
|
|
|
|
/***/ }),
|
|
/* 343 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class ReferenceManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideReferences(document, position, context, token) {
|
|
let providers = this.getProviders(document);
|
|
if (!providers.length)
|
|
return null;
|
|
let arr = await Promise.all(providers.map(item => {
|
|
let { provider } = item;
|
|
return Promise.resolve(provider.provideReferences(document, position, context, token));
|
|
}));
|
|
return this.mergeDefinitions(arr);
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = ReferenceManager;
|
|
//# sourceMappingURL=referenceManager.js.map
|
|
|
|
/***/ }),
|
|
/* 344 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class RenameManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideRenameEdits(document, position, newName, token) {
|
|
let item = this.getProvider(document);
|
|
if (!item)
|
|
return null;
|
|
let { provider } = item;
|
|
return await Promise.resolve(provider.provideRenameEdits(document, position, newName, token));
|
|
}
|
|
async prepareRename(document, position, token) {
|
|
let item = this.getProvider(document);
|
|
if (!item)
|
|
return null;
|
|
let { provider } = item;
|
|
if (provider.prepareRename == null)
|
|
return null;
|
|
let res = await Promise.resolve(provider.prepareRename(document, position, token));
|
|
// can not rename
|
|
if (res == null)
|
|
false;
|
|
return res;
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = RenameManager;
|
|
//# sourceMappingURL=renameManager.js.map
|
|
|
|
/***/ }),
|
|
/* 345 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class SignatureManager extends manager_1.default {
|
|
register(selector, provider, triggerCharacters) {
|
|
let characters = triggerCharacters.reduce((p, c) => {
|
|
return p.concat(c.split(/\s*/g));
|
|
}, []);
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider,
|
|
triggerCharacters: characters
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
shouldTrigger(document, triggerCharacter) {
|
|
let item = this.getProvider(document);
|
|
if (!item)
|
|
return false;
|
|
let { triggerCharacters } = item;
|
|
return triggerCharacters && triggerCharacters.indexOf(triggerCharacter) != -1;
|
|
}
|
|
async provideSignatureHelp(document, position, token) {
|
|
let item = this.getProvider(document);
|
|
if (!item)
|
|
return null;
|
|
let res = await Promise.resolve(item.provider.provideSignatureHelp(document, position, token));
|
|
if (res && res.signatures && res.signatures.length)
|
|
return res;
|
|
return null;
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = SignatureManager;
|
|
//# sourceMappingURL=signatureManager.js.map
|
|
|
|
/***/ }),
|
|
/* 346 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class TypeDefinitionManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideTypeDefinition(document, position, token) {
|
|
let providers = this.getProviders(document);
|
|
if (!providers.length)
|
|
return null;
|
|
let arr = await Promise.all(providers.map(item => {
|
|
let { provider } = item;
|
|
return Promise.resolve(provider.provideTypeDefinition(document, position, token));
|
|
}));
|
|
return this.mergeDefinitions(arr);
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = TypeDefinitionManager;
|
|
//# sourceMappingURL=typeDefinitionManager.js.map
|
|
|
|
/***/ }),
|
|
/* 347 */
|
|
/***/ (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__(149);
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(328));
|
|
const uuid = __webpack_require__(321);
|
|
class WorkspaceSymbolManager extends manager_1.default {
|
|
register(selector, provider) {
|
|
let item = {
|
|
id: uuid(),
|
|
selector,
|
|
provider
|
|
};
|
|
this.providers.add(item);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
this.providers.delete(item);
|
|
});
|
|
}
|
|
async provideWorkspaceSymbols(document, query, token) {
|
|
let item = this.getProvider(document);
|
|
if (!item)
|
|
return null;
|
|
let { provider } = item;
|
|
let res = await Promise.resolve(provider.provideWorkspaceSymbols(query, token));
|
|
res = res || [];
|
|
for (let sym of res) {
|
|
sym.source = item.id;
|
|
}
|
|
return res;
|
|
}
|
|
async resolveWorkspaceSymbol(symbolInfo, token) {
|
|
let item = Array.from(this.providers).find(o => o.id == symbolInfo.source);
|
|
if (!item)
|
|
return;
|
|
let { provider } = item;
|
|
if (typeof provider.resolveWorkspaceSymbol != 'function') {
|
|
return Promise.resolve(symbolInfo);
|
|
}
|
|
return await Promise.resolve(provider.resolveWorkspaceSymbol(symbolInfo, token));
|
|
}
|
|
dispose() {
|
|
this.providers = new Set();
|
|
}
|
|
}
|
|
exports.default = WorkspaceSymbolManager;
|
|
//# sourceMappingURL=workspaceSymbolsManager.js.map
|
|
|
|
/***/ }),
|
|
/* 348 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const vscode_languageserver_types_1 = __webpack_require__(161);
|
|
const parser_1 = __webpack_require__(234);
|
|
const string_1 = __webpack_require__(210);
|
|
const logger = __webpack_require__(186)('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
|
|
|
|
/***/ }),
|
|
/* 349 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const ansiparse_1 = __webpack_require__(350);
|
|
const string_1 = __webpack_require__(210);
|
|
/**
|
|
* Build highlights, with lines and highlights
|
|
*/
|
|
class Highlighter {
|
|
constructor(srcId = -1) {
|
|
this.srcId = srcId;
|
|
this.lines = [];
|
|
this.highlights = [];
|
|
}
|
|
addLine(line, hlGroup) {
|
|
if (line.indexOf('\n') !== -1) {
|
|
for (let content of line.split(/\r?\n/)) {
|
|
this.addLine(content, hlGroup);
|
|
}
|
|
return;
|
|
}
|
|
if (hlGroup) {
|
|
this.highlights.push({
|
|
line: this.lines.length,
|
|
colStart: line.match(/^\s*/)[0].length,
|
|
colEnd: string_1.byteLength(line),
|
|
hlGroup
|
|
});
|
|
} // '\x1b'
|
|
if (line.indexOf('\x1b') !== -1) {
|
|
let res = ansiparse_1.parseAnsiHighlights(line);
|
|
for (let hl of res.highlights) {
|
|
let { span, hlGroup } = hl;
|
|
if (span[0] != span[1]) {
|
|
this.highlights.push({
|
|
line: this.lines.length,
|
|
colStart: span[0],
|
|
colEnd: span[1],
|
|
hlGroup
|
|
});
|
|
}
|
|
}
|
|
this.lines.push(res.line);
|
|
}
|
|
else {
|
|
this.lines.push(line);
|
|
}
|
|
}
|
|
addLines(lines) {
|
|
this.lines.push(...lines);
|
|
}
|
|
addText(text, hlGroup) {
|
|
let { lines } = this;
|
|
let pre = lines[lines.length - 1] || '';
|
|
if (hlGroup) {
|
|
let colStart = string_1.byteLength(pre);
|
|
this.highlights.push({
|
|
line: lines.length ? lines.length - 1 : 0,
|
|
colStart,
|
|
colEnd: colStart + string_1.byteLength(text),
|
|
hlGroup
|
|
});
|
|
}
|
|
if (lines.length) {
|
|
lines[lines.length - 1] = `${pre}${text}`;
|
|
}
|
|
else {
|
|
lines.push(text);
|
|
}
|
|
}
|
|
get length() {
|
|
return this.lines.length;
|
|
}
|
|
getline(line) {
|
|
return this.lines[line] || '';
|
|
}
|
|
// default to replace
|
|
render(buffer, start = 0, end = -1) {
|
|
buffer.setLines(this.lines, { start, end, strictIndexing: false }, true);
|
|
for (let item of this.highlights) {
|
|
buffer.addHighlight({
|
|
hlGroup: item.hlGroup,
|
|
colStart: item.colStart,
|
|
colEnd: item.colEnd == null ? -1 : item.colEnd,
|
|
line: start + item.line,
|
|
srcId: this.srcId
|
|
}).logError();
|
|
}
|
|
}
|
|
}
|
|
exports.default = Highlighter;
|
|
//# sourceMappingURL=highligher.js.map
|
|
|
|
/***/ }),
|
|
/* 350 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const string_1 = __webpack_require__(210);
|
|
const foregroundColors = {
|
|
30: 'black',
|
|
31: 'red',
|
|
32: 'green',
|
|
33: 'yellow',
|
|
34: 'blue',
|
|
35: 'magenta',
|
|
36: 'cyan',
|
|
37: 'white',
|
|
90: 'grey'
|
|
};
|
|
const backgroundColors = {
|
|
40: 'black',
|
|
41: 'red',
|
|
42: 'green',
|
|
43: 'yellow',
|
|
44: 'blue',
|
|
45: 'magenta',
|
|
46: 'cyan',
|
|
47: 'white'
|
|
};
|
|
const styles = {
|
|
1: 'bold',
|
|
3: 'italic',
|
|
4: 'underline'
|
|
};
|
|
function parseAnsiHighlights(line) {
|
|
let items = ansiparse(line);
|
|
let highlights = [];
|
|
let newLabel = '';
|
|
for (let item of items) {
|
|
if (!item.text)
|
|
continue;
|
|
let { foreground, background } = item;
|
|
let len = string_1.byteLength(newLabel);
|
|
if (foreground || background) {
|
|
let span = [len, len + string_1.byteLength(item.text)];
|
|
let hlGroup = '';
|
|
if (foreground && background) {
|
|
hlGroup = `CocList${string_1.upperFirst(foreground)}${string_1.upperFirst(background)}`;
|
|
}
|
|
else if (foreground) {
|
|
hlGroup = `CocListFg${string_1.upperFirst(foreground)}`;
|
|
}
|
|
else if (background) {
|
|
hlGroup = `CocListBg${string_1.upperFirst(background)}`;
|
|
}
|
|
highlights.push({ span, hlGroup });
|
|
}
|
|
newLabel = newLabel + item.text;
|
|
}
|
|
return { line: newLabel, highlights };
|
|
}
|
|
exports.parseAnsiHighlights = parseAnsiHighlights;
|
|
function ansiparse(str) {
|
|
//
|
|
// I'm terrible at writing parsers.
|
|
//
|
|
let matchingControl = null;
|
|
let matchingData = null;
|
|
let matchingText = '';
|
|
let ansiState = [];
|
|
let result = [];
|
|
let state = {};
|
|
let eraseChar;
|
|
//
|
|
// General workflow for this thing is:
|
|
// \033\[33mText
|
|
// | | |
|
|
// | | matchingText
|
|
// | matchingData
|
|
// matchingControl
|
|
//
|
|
// \033\[K or \033\[m
|
|
//
|
|
// In further steps we hope it's all going to be fine. It usually is.
|
|
//
|
|
//
|
|
// Erases a char from the output
|
|
//
|
|
eraseChar = () => {
|
|
let index;
|
|
let text;
|
|
if (matchingText.length) {
|
|
matchingText = matchingText.substr(0, matchingText.length - 1);
|
|
}
|
|
else if (result.length) {
|
|
index = result.length - 1;
|
|
text = result[index].text;
|
|
if (text.length === 1) {
|
|
//
|
|
// A result bit was fully deleted, pop it out to simplify the final output
|
|
//
|
|
result.pop();
|
|
}
|
|
else {
|
|
result[index].text = text.substr(0, text.length - 1);
|
|
}
|
|
}
|
|
};
|
|
for (let i = 0; i < str.length; i++) { // tslint:disable-line
|
|
if (matchingControl != null) {
|
|
if (matchingControl == '\x1b' && str[i] == '\[') {
|
|
//
|
|
// We've matched full control code. Lets start matching formating data.
|
|
//
|
|
//
|
|
// "emit" matched text with correct state
|
|
//
|
|
if (matchingText) {
|
|
state.text = matchingText;
|
|
result.push(state);
|
|
state = {};
|
|
matchingText = '';
|
|
}
|
|
if (matchingText == '' && (str[i + 1] == 'm' || str[i + 1] == 'K')) {
|
|
if (state.foreground || state.background) {
|
|
state.text = '';
|
|
result.push(state);
|
|
}
|
|
state = {};
|
|
}
|
|
matchingControl = null;
|
|
matchingData = '';
|
|
}
|
|
else {
|
|
//
|
|
// We failed to match anything - most likely a bad control code. We
|
|
// go back to matching regular strings.
|
|
//
|
|
matchingText += matchingControl + str[i];
|
|
matchingControl = null;
|
|
}
|
|
continue;
|
|
}
|
|
else if (matchingData != null) {
|
|
if (str[i] == ';') {
|
|
//
|
|
// `;` separates many formatting codes, for example: `\033[33;43m`
|
|
// means that both `33` and `43` should be applied.
|
|
//
|
|
// TODO: this can be simplified by modifying state here.
|
|
//
|
|
ansiState.push(matchingData);
|
|
matchingData = '';
|
|
}
|
|
else if (str[i] == 'm' || str[i] == 'K') {
|
|
//
|
|
// `m` finished whole formatting code. We can proceed to matching
|
|
// formatted text.
|
|
//
|
|
ansiState.push(matchingData);
|
|
matchingData = null;
|
|
matchingText = '';
|
|
//
|
|
// Convert matched formatting data into user-friendly state object.
|
|
//
|
|
// TODO: DRY.
|
|
//
|
|
ansiState.forEach(ansiCode => {
|
|
if (foregroundColors[ansiCode]) {
|
|
state.foreground = foregroundColors[ansiCode];
|
|
}
|
|
else if (backgroundColors[ansiCode]) {
|
|
state.background = backgroundColors[ansiCode];
|
|
}
|
|
else if (ansiCode == 39) {
|
|
delete state.foreground;
|
|
}
|
|
else if (ansiCode == 49) {
|
|
delete state.background;
|
|
}
|
|
else if (styles[ansiCode]) {
|
|
state[styles[ansiCode]] = true;
|
|
}
|
|
else if (ansiCode == 22) {
|
|
state.bold = false;
|
|
}
|
|
else if (ansiCode == 23) {
|
|
state.italic = false;
|
|
}
|
|
else if (ansiCode == 24) {
|
|
state.underline = false;
|
|
}
|
|
});
|
|
ansiState = [];
|
|
}
|
|
else {
|
|
matchingData += str[i];
|
|
}
|
|
continue;
|
|
}
|
|
if (str[i] == '\x1b') {
|
|
matchingControl = str[i];
|
|
}
|
|
else if (str[i] == '\u0008') {
|
|
eraseChar();
|
|
}
|
|
else {
|
|
matchingText += str[i];
|
|
}
|
|
}
|
|
if (matchingText) {
|
|
state.text = matchingText + (matchingControl ? matchingControl : '');
|
|
result.push(state);
|
|
}
|
|
return result;
|
|
}
|
|
exports.ansiparse = ansiparse;
|
|
//# sourceMappingURL=ansiparse.js.map
|
|
|
|
/***/ }),
|
|
/* 351 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const events_1 = __webpack_require__(49);
|
|
const fs_1 = tslib_1.__importDefault(__webpack_require__(55));
|
|
const net_1 = tslib_1.__importDefault(__webpack_require__(6));
|
|
const os_1 = tslib_1.__importDefault(__webpack_require__(56));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const language_client_1 = __webpack_require__(352);
|
|
const types_1 = __webpack_require__(189);
|
|
const util_1 = __webpack_require__(174);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('services');
|
|
function getStateName(state) {
|
|
switch (state) {
|
|
case types_1.ServiceStat.Initial:
|
|
return 'init';
|
|
case types_1.ServiceStat.Running:
|
|
return 'running';
|
|
case types_1.ServiceStat.Starting:
|
|
return 'starting';
|
|
case types_1.ServiceStat.StartFailed:
|
|
return 'startFailed';
|
|
case types_1.ServiceStat.Stopping:
|
|
return 'stopping';
|
|
case types_1.ServiceStat.Stopped:
|
|
return 'stopped';
|
|
default:
|
|
return 'unknown';
|
|
}
|
|
}
|
|
exports.getStateName = getStateName;
|
|
class ServiceManager extends events_1.EventEmitter {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.registered = new Map();
|
|
this.disposables = [];
|
|
}
|
|
init() {
|
|
workspace_1.default.onDidOpenTextDocument(document => {
|
|
this.start(document);
|
|
}, null, this.disposables);
|
|
workspace_1.default.onDidChangeConfiguration(e => {
|
|
if (e.affectsConfiguration('languageserver')) {
|
|
this.createCustomServices();
|
|
}
|
|
}, null, this.disposables);
|
|
this.createCustomServices();
|
|
}
|
|
dispose() {
|
|
this.removeAllListeners();
|
|
util_1.disposeAll(this.disposables);
|
|
for (let service of this.registered.values()) {
|
|
service.dispose();
|
|
}
|
|
}
|
|
regist(service) {
|
|
let { id } = service;
|
|
if (!id)
|
|
logger.error('invalid service configuration. ', service.name);
|
|
if (this.registered.get(id))
|
|
return;
|
|
this.registered.set(id, service);
|
|
logger.info(`registered service "${id}"`);
|
|
if (this.shouldStart(service)) {
|
|
service.start(); // tslint:disable-line
|
|
}
|
|
if (service.state == types_1.ServiceStat.Running) {
|
|
this.emit('ready', id);
|
|
}
|
|
service.onServiceReady(() => {
|
|
logger.info(`service ${id} started`);
|
|
this.emit('ready', id);
|
|
}, null, this.disposables);
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
service.stop();
|
|
service.dispose();
|
|
this.registered.delete(id);
|
|
});
|
|
}
|
|
getService(id) {
|
|
let service = this.registered.get(id);
|
|
if (!service)
|
|
service = this.registered.get(`languageserver.${id}`);
|
|
return service;
|
|
}
|
|
hasService(id) {
|
|
return this.registered.has(id);
|
|
}
|
|
shouldStart(service) {
|
|
if (service.state != types_1.ServiceStat.Initial) {
|
|
return false;
|
|
}
|
|
let selector = service.selector;
|
|
for (let doc of workspace_1.default.documents) {
|
|
if (workspace_1.default.match(selector, doc.textDocument)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
start(document) {
|
|
let services = this.getServices(document);
|
|
for (let service of services) {
|
|
if (service.state == types_1.ServiceStat.Initial) {
|
|
service.start(); // tslint:disable-line
|
|
}
|
|
}
|
|
}
|
|
getServices(document) {
|
|
let res = [];
|
|
for (let service of this.registered.values()) {
|
|
if (workspace_1.default.match(service.selector, document) > 0) {
|
|
res.push(service);
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
stop(id) {
|
|
let service = this.registered.get(id);
|
|
if (!service) {
|
|
workspace_1.default.showMessage(`Service ${id} not found`, 'error');
|
|
return;
|
|
}
|
|
return Promise.resolve(service.stop());
|
|
}
|
|
async stopAll() {
|
|
for (let service of this.registered.values()) {
|
|
await Promise.resolve(service.stop());
|
|
}
|
|
}
|
|
async toggle(id) {
|
|
let service = this.registered.get(id);
|
|
if (!service) {
|
|
workspace_1.default.showMessage(`Service ${id} not found`, 'error');
|
|
return;
|
|
}
|
|
let { state } = service;
|
|
try {
|
|
if (state == types_1.ServiceStat.Running) {
|
|
await Promise.resolve(service.stop());
|
|
}
|
|
else if (state == types_1.ServiceStat.Initial) {
|
|
await service.start();
|
|
}
|
|
else if (state == types_1.ServiceStat.Stopped) {
|
|
await service.restart();
|
|
}
|
|
}
|
|
catch (e) {
|
|
workspace_1.default.showMessage(`Service error: ${e.message}`, 'error');
|
|
}
|
|
}
|
|
getServiceStats() {
|
|
let res = [];
|
|
for (let [id, service] of this.registered) {
|
|
res.push({
|
|
id,
|
|
languageIds: documentSelectorToLanguageIds(service.selector),
|
|
state: getStateName(service.state)
|
|
});
|
|
}
|
|
return res;
|
|
}
|
|
createCustomServices() {
|
|
let base = 'languageserver';
|
|
let lspConfig = workspace_1.default.getConfiguration().get(base, {});
|
|
for (let key of Object.keys(lspConfig)) {
|
|
if (this.registered.get(key))
|
|
continue;
|
|
let config = lspConfig[key];
|
|
let id = `${base}.${key}`;
|
|
if (config.enable === false || this.hasService(id))
|
|
continue;
|
|
let opts = getLanguageServerOptions(id, key, config);
|
|
if (!opts)
|
|
continue;
|
|
let client = new language_client_1.LanguageClient(id, key, opts[1], opts[0]);
|
|
this.registLanguageClient(client);
|
|
}
|
|
}
|
|
waitClient(id) {
|
|
let service = this.getService(id);
|
|
if (service && service.state == types_1.ServiceStat.Running)
|
|
return Promise.resolve();
|
|
if (service)
|
|
return new Promise(resolve => {
|
|
service.onServiceReady(() => {
|
|
resolve();
|
|
});
|
|
});
|
|
return new Promise(resolve => {
|
|
let listener = clientId => {
|
|
if (clientId == id || clientId == `languageserver.${id}`) {
|
|
this.off('ready', listener);
|
|
resolve();
|
|
}
|
|
};
|
|
this.on('ready', listener);
|
|
});
|
|
}
|
|
async registNotification(id, method) {
|
|
await this.waitClient(id);
|
|
let service = this.getService(id);
|
|
if (!service.client) {
|
|
workspace_1.default.showMessage(`Not a language client: ${id}`, 'error');
|
|
return;
|
|
}
|
|
let client = service.client;
|
|
client.onNotification(method, async (result) => {
|
|
await workspace_1.default.nvim.call('coc#do_notify', [id, method, result]);
|
|
});
|
|
}
|
|
async sendRequest(id, method, params) {
|
|
if (!method) {
|
|
throw new Error(`method required for sendRequest`);
|
|
}
|
|
let service = this.getService(id);
|
|
// wait for extension activate
|
|
if (!service)
|
|
await util_1.wait(100);
|
|
service = this.getService(id);
|
|
if (!service || !service.client) {
|
|
throw new Error(`Language server ${id} not found`);
|
|
}
|
|
if (service.state == types_1.ServiceStat.Starting) {
|
|
await service.client.onReady();
|
|
}
|
|
if (service.state != types_1.ServiceStat.Running) {
|
|
throw new Error(`Language server ${id} not running`);
|
|
}
|
|
return await Promise.resolve(service.client.sendRequest(method, params));
|
|
}
|
|
registLanguageClient(client) {
|
|
let disposables = [];
|
|
let onDidServiceReady = new vscode_languageserver_protocol_1.Emitter();
|
|
let service = {
|
|
client,
|
|
id: client.id,
|
|
name: client.name,
|
|
selector: client.clientOptions.documentSelector,
|
|
state: types_1.ServiceStat.Initial,
|
|
onServiceReady: onDidServiceReady.event,
|
|
start: () => {
|
|
if (service.state != types_1.ServiceStat.Initial && service.state != types_1.ServiceStat.Stopped) {
|
|
return Promise.resolve();
|
|
}
|
|
if (client.getPublicState() == language_client_1.State.Starting) {
|
|
return Promise.resolve();
|
|
}
|
|
service.state = types_1.ServiceStat.Starting;
|
|
logger.debug(`starting service: ${client.name}`);
|
|
let disposable = client.start();
|
|
disposables.push(disposable);
|
|
return new Promise(resolve => {
|
|
client.onReady().then(() => {
|
|
onDidServiceReady.fire(void 0);
|
|
resolve();
|
|
}, e => {
|
|
workspace_1.default.showMessage(`Server ${client.name} failed to start: ${e ? e.message : ''}`, 'error');
|
|
service.state = types_1.ServiceStat.StartFailed;
|
|
resolve();
|
|
});
|
|
});
|
|
},
|
|
dispose: () => {
|
|
client.stop();
|
|
onDidServiceReady.dispose();
|
|
util_1.disposeAll(disposables);
|
|
},
|
|
stop: async () => {
|
|
return await Promise.resolve(client.stop());
|
|
},
|
|
restart: async () => {
|
|
if (service.state == types_1.ServiceStat.Running) {
|
|
await service.stop();
|
|
}
|
|
service.state = types_1.ServiceStat.Starting;
|
|
client.restart();
|
|
},
|
|
};
|
|
client.onDidChangeState(changeEvent => {
|
|
let { oldState, newState } = changeEvent;
|
|
if (newState == language_client_1.State.Starting) {
|
|
service.state = types_1.ServiceStat.Starting;
|
|
}
|
|
else if (newState == language_client_1.State.Running) {
|
|
service.state = types_1.ServiceStat.Running;
|
|
}
|
|
else if (newState == language_client_1.State.Stopped) {
|
|
service.state = types_1.ServiceStat.Stopped;
|
|
}
|
|
let oldStr = stateString(oldState);
|
|
let newStr = stateString(newState);
|
|
logger.info(`${client.name} state change: ${oldStr} => ${newStr}`);
|
|
}, null, disposables);
|
|
return this.regist(service);
|
|
}
|
|
}
|
|
exports.ServiceManager = ServiceManager;
|
|
function documentSelectorToLanguageIds(documentSelector) {
|
|
let res = documentSelector.map(filter => {
|
|
if (typeof filter == 'string') {
|
|
return filter;
|
|
}
|
|
return filter.language;
|
|
});
|
|
res = res.filter(s => typeof s == 'string');
|
|
return res;
|
|
}
|
|
exports.documentSelectorToLanguageIds = documentSelectorToLanguageIds;
|
|
// convert config to options
|
|
function getLanguageServerOptions(id, name, config) {
|
|
let { command, module, port, args, filetypes } = config;
|
|
args = args || [];
|
|
if (!filetypes) {
|
|
workspace_1.default.showMessage(`Wrong configuration of LS "${name}", filetypes not found`, 'error');
|
|
return null;
|
|
}
|
|
if (!command && !module && !port) {
|
|
workspace_1.default.showMessage(`Wrong configuration of LS "${name}", no command or module specified.`, 'error');
|
|
return null;
|
|
}
|
|
if (module && !fs_1.default.existsSync(module)) {
|
|
workspace_1.default.showMessage(`Module file "${module}" not found for LS "${name}"`, 'error');
|
|
return null;
|
|
}
|
|
if (filetypes.length == 0)
|
|
return;
|
|
let isModule = module != null;
|
|
let serverOptions;
|
|
if (isModule) {
|
|
serverOptions = {
|
|
module: module.toString(),
|
|
runtime: config.runtime || process.execPath,
|
|
args,
|
|
transport: getTransportKind(config),
|
|
options: getForkOptions(config)
|
|
};
|
|
}
|
|
else if (command) {
|
|
serverOptions = {
|
|
command,
|
|
args,
|
|
options: getSpawnOptions(config)
|
|
};
|
|
}
|
|
else if (port) {
|
|
serverOptions = () => {
|
|
return new Promise((resolve, reject) => {
|
|
let client = new net_1.default.Socket();
|
|
client.connect(port, config.host || '127.0.0.1', () => {
|
|
resolve({
|
|
reader: client,
|
|
writer: client
|
|
});
|
|
});
|
|
client.on('error', e => {
|
|
reject(new Error(`Connection error for ${id}: ${e.message}`));
|
|
});
|
|
});
|
|
};
|
|
}
|
|
let documentSelector = [];
|
|
config.filetypes.forEach(filetype => {
|
|
let schemes = ['file', 'untitled'].concat(config.additionalSchemes || []);
|
|
documentSelector.push(...schemes.map(scheme => {
|
|
return { language: filetype, scheme };
|
|
}));
|
|
});
|
|
if (documentSelector.length == 0) {
|
|
documentSelector = [{ scheme: 'file' }, { scheme: 'untitled' }];
|
|
}
|
|
let disableWorkspaceFolders = !!config.disableWorkspaceFolders;
|
|
let ignoredRootPaths = config.ignoredRootPaths || [];
|
|
ignoredRootPaths = ignoredRootPaths.map(s => s.replace(/^~/, os_1.default.homedir()));
|
|
let clientOptions = {
|
|
ignoredRootPaths,
|
|
disableWorkspaceFolders,
|
|
disableDynamicRegister: !!config.disableDynamicRegister,
|
|
disableCompletion: !!config.disableCompletion,
|
|
disableDiagnostics: !!config.disableDiagnostics,
|
|
documentSelector,
|
|
revealOutputChannelOn: getRevealOutputChannelOn(config.revealOutputChannelOn),
|
|
synchronize: {
|
|
configurationSection: `${id}.settings`
|
|
},
|
|
diagnosticCollectionName: name,
|
|
outputChannelName: id,
|
|
stdioEncoding: config.stdioEncoding || 'utf8',
|
|
initializationOptions: config.initializationOptions || {}
|
|
};
|
|
return [clientOptions, serverOptions];
|
|
}
|
|
exports.getLanguageServerOptions = getLanguageServerOptions;
|
|
function getRevealOutputChannelOn(revealOn) {
|
|
switch (revealOn) {
|
|
case 'info':
|
|
return language_client_1.RevealOutputChannelOn.Info;
|
|
case 'warn':
|
|
return language_client_1.RevealOutputChannelOn.Warn;
|
|
case 'error':
|
|
return language_client_1.RevealOutputChannelOn.Error;
|
|
case 'never':
|
|
return language_client_1.RevealOutputChannelOn.Never;
|
|
default:
|
|
return language_client_1.RevealOutputChannelOn.Never;
|
|
}
|
|
}
|
|
exports.getRevealOutputChannelOn = getRevealOutputChannelOn;
|
|
function getTransportKind(config) {
|
|
let { transport, transportPort } = config;
|
|
if (!transport || transport == 'ipc')
|
|
return language_client_1.TransportKind.ipc;
|
|
if (transport == 'stdio')
|
|
return language_client_1.TransportKind.stdio;
|
|
if (transport == 'pipe')
|
|
return language_client_1.TransportKind.pipe;
|
|
return { kind: language_client_1.TransportKind.socket, port: transportPort };
|
|
}
|
|
exports.getTransportKind = getTransportKind;
|
|
function getForkOptions(config) {
|
|
return {
|
|
cwd: config.cwd,
|
|
execArgv: config.execArgv || [],
|
|
env: config.env || undefined
|
|
};
|
|
}
|
|
function getSpawnOptions(config) {
|
|
return {
|
|
cwd: config.cwd,
|
|
detached: !!config.detached,
|
|
shell: !!config.shell,
|
|
env: config.env || undefined
|
|
};
|
|
}
|
|
function stateString(state) {
|
|
switch (state) {
|
|
case language_client_1.State.Running:
|
|
return 'running';
|
|
case language_client_1.State.Starting:
|
|
return 'starting';
|
|
case language_client_1.State.Stopped:
|
|
return 'stopped';
|
|
}
|
|
return 'unknown';
|
|
}
|
|
exports.default = new ServiceManager();
|
|
//# sourceMappingURL=services.js.map
|
|
|
|
/***/ }),
|
|
/* 352 */
|
|
/***/ (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 child_process_1 = tslib_1.__importDefault(__webpack_require__(175));
|
|
const fs_1 = tslib_1.__importDefault(__webpack_require__(55));
|
|
const os_1 = tslib_1.__importDefault(__webpack_require__(56));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const types_1 = __webpack_require__(189);
|
|
const util_1 = __webpack_require__(174);
|
|
const Is = tslib_1.__importStar(__webpack_require__(191));
|
|
const processes_1 = __webpack_require__(320);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const which_1 = tslib_1.__importDefault(__webpack_require__(181));
|
|
const client_1 = __webpack_require__(353);
|
|
const colorProvider_1 = __webpack_require__(357);
|
|
const configuration_1 = __webpack_require__(358);
|
|
const declaration_1 = __webpack_require__(359);
|
|
const foldingRange_1 = __webpack_require__(360);
|
|
const implementation_1 = __webpack_require__(361);
|
|
const typeDefinition_1 = __webpack_require__(362);
|
|
const workspaceFolders_1 = __webpack_require__(363);
|
|
const string_1 = __webpack_require__(210);
|
|
const logger = __webpack_require__(186)('language-client-index');
|
|
tslib_1.__exportStar(__webpack_require__(353), exports);
|
|
var Executable;
|
|
(function (Executable) {
|
|
function is(value) {
|
|
return Is.string(value.command);
|
|
}
|
|
Executable.is = is;
|
|
})(Executable || (Executable = {}));
|
|
var TransportKind;
|
|
(function (TransportKind) {
|
|
TransportKind[TransportKind["stdio"] = 0] = "stdio";
|
|
TransportKind[TransportKind["ipc"] = 1] = "ipc";
|
|
TransportKind[TransportKind["pipe"] = 2] = "pipe";
|
|
TransportKind[TransportKind["socket"] = 3] = "socket";
|
|
})(TransportKind = exports.TransportKind || (exports.TransportKind = {}));
|
|
var Transport;
|
|
(function (Transport) {
|
|
function isSocket(value) {
|
|
let candidate = value;
|
|
return (candidate &&
|
|
candidate.kind === TransportKind.socket &&
|
|
Is.number(candidate.port));
|
|
}
|
|
Transport.isSocket = isSocket;
|
|
})(Transport || (Transport = {}));
|
|
var NodeModule;
|
|
(function (NodeModule) {
|
|
function is(value) {
|
|
return Is.string(value.module);
|
|
}
|
|
NodeModule.is = is;
|
|
})(NodeModule || (NodeModule = {}));
|
|
var StreamInfo;
|
|
(function (StreamInfo) {
|
|
function is(value) {
|
|
let candidate = value;
|
|
return (candidate && candidate.writer !== void 0 && candidate.reader !== void 0);
|
|
}
|
|
StreamInfo.is = is;
|
|
})(StreamInfo || (StreamInfo = {}));
|
|
var ChildProcessInfo;
|
|
(function (ChildProcessInfo) {
|
|
function is(value) {
|
|
let candidate = value;
|
|
return (candidate &&
|
|
candidate.process !== void 0 &&
|
|
typeof candidate.detached === 'boolean');
|
|
}
|
|
ChildProcessInfo.is = is;
|
|
})(ChildProcessInfo || (ChildProcessInfo = {}));
|
|
class LanguageClient extends client_1.BaseLanguageClient {
|
|
constructor(arg1, arg2, arg3, arg4, arg5) {
|
|
let id;
|
|
let name;
|
|
let serverOptions;
|
|
let clientOptions;
|
|
let forceDebug;
|
|
if (Is.string(arg2)) {
|
|
id = arg1;
|
|
name = arg2;
|
|
serverOptions = arg3;
|
|
clientOptions = arg4;
|
|
forceDebug = !!arg5;
|
|
}
|
|
else {
|
|
id = arg1.toLowerCase();
|
|
name = arg1;
|
|
serverOptions = arg2;
|
|
clientOptions = arg3;
|
|
forceDebug = arg4;
|
|
}
|
|
if (forceDebug === void 0) {
|
|
forceDebug = false;
|
|
}
|
|
super(id, name, clientOptions);
|
|
this._serverOptions = serverOptions;
|
|
this._forceDebug = forceDebug;
|
|
this.registerProposedFeatures();
|
|
}
|
|
stop() {
|
|
return super.stop().then(() => {
|
|
if (this._serverProcess) {
|
|
let toCheck = this._serverProcess;
|
|
this._serverProcess = undefined;
|
|
if (this._isDetached === void 0 || !this._isDetached) {
|
|
this.checkProcessDied(toCheck);
|
|
}
|
|
this._isDetached = undefined;
|
|
}
|
|
});
|
|
}
|
|
get serviceState() {
|
|
let state = this._state;
|
|
switch (state) {
|
|
case client_1.ClientState.Initial:
|
|
return types_1.ServiceStat.Initial;
|
|
case client_1.ClientState.Running:
|
|
return types_1.ServiceStat.Running;
|
|
case client_1.ClientState.StartFailed:
|
|
return types_1.ServiceStat.StartFailed;
|
|
case client_1.ClientState.Starting:
|
|
return types_1.ServiceStat.Starting;
|
|
case client_1.ClientState.Stopped:
|
|
return types_1.ServiceStat.Stopped;
|
|
case client_1.ClientState.Stopping:
|
|
return types_1.ServiceStat.Stopping;
|
|
default:
|
|
logger.error(`Unknown state: ${state}`);
|
|
return types_1.ServiceStat.Stopped;
|
|
}
|
|
}
|
|
static stateName(state) {
|
|
switch (state) {
|
|
case client_1.ClientState.Initial:
|
|
return 'Initial';
|
|
case client_1.ClientState.Running:
|
|
return 'Running';
|
|
case client_1.ClientState.StartFailed:
|
|
return 'StartFailed';
|
|
case client_1.ClientState.Starting:
|
|
return 'Starting';
|
|
case client_1.ClientState.Stopped:
|
|
return 'Stopped';
|
|
case client_1.ClientState.Stopping:
|
|
return 'Stopping';
|
|
default:
|
|
return 'Unknonw';
|
|
}
|
|
}
|
|
checkProcessDied(childProcess) {
|
|
if (!childProcess || global.hasOwnProperty('__TEST__'))
|
|
return;
|
|
setTimeout(() => {
|
|
// Test if the process is still alive. Throws an exception if not
|
|
try {
|
|
process.kill(childProcess.pid, 0);
|
|
processes_1.terminate(childProcess);
|
|
}
|
|
catch (error) {
|
|
// All is fine.
|
|
}
|
|
}, 1000);
|
|
}
|
|
handleConnectionClosed() {
|
|
this._serverProcess = undefined;
|
|
super.handleConnectionClosed();
|
|
}
|
|
async createMessageTransports(encoding) {
|
|
function getEnvironment(env) {
|
|
if (!env)
|
|
return process.env;
|
|
return Object.assign({}, process.env, env);
|
|
}
|
|
function startedInDebugMode() {
|
|
let args = process.execArgv;
|
|
if (args) {
|
|
return args.some(arg => /^--debug=?/.test(arg) ||
|
|
/^--debug-brk=?/.test(arg) ||
|
|
/^--inspect=?/.test(arg) ||
|
|
/^--inspect-brk=?/.test(arg));
|
|
}
|
|
return false;
|
|
}
|
|
let server = this._serverOptions;
|
|
// We got a function.
|
|
if (Is.func(server)) {
|
|
let result = await Promise.resolve(server());
|
|
if (client_1.MessageTransports.is(result)) {
|
|
this._isDetached = !!result.detached;
|
|
return result;
|
|
}
|
|
else if (StreamInfo.is(result)) {
|
|
this._isDetached = !!result.detached;
|
|
return {
|
|
reader: new vscode_languageserver_protocol_1.StreamMessageReader(result.reader),
|
|
writer: new vscode_languageserver_protocol_1.StreamMessageWriter(result.writer)
|
|
};
|
|
}
|
|
else {
|
|
let cp;
|
|
if (ChildProcessInfo.is(result)) {
|
|
cp = result.process;
|
|
this._isDetached = result.detached;
|
|
}
|
|
else {
|
|
cp = result;
|
|
this._isDetached = false;
|
|
}
|
|
cp.stderr.on('data', data => this.appendOutput(data, encoding));
|
|
return {
|
|
reader: new vscode_languageserver_protocol_1.StreamMessageReader(cp.stdout),
|
|
writer: new vscode_languageserver_protocol_1.StreamMessageWriter(cp.stdin)
|
|
};
|
|
}
|
|
}
|
|
let json = server;
|
|
let runDebug = server;
|
|
if (runDebug.run || runDebug.debug) {
|
|
// We are under debugging. So use debug as well.
|
|
if (typeof v8debug === 'object' || this._forceDebug || startedInDebugMode()) {
|
|
json = runDebug.debug;
|
|
}
|
|
else {
|
|
json = runDebug.run;
|
|
}
|
|
}
|
|
else {
|
|
json = server;
|
|
}
|
|
let serverWorkingDir = await this._getServerWorkingDir(json.options);
|
|
if (NodeModule.is(json) && json.module) {
|
|
let node = json;
|
|
let transport = node.transport || TransportKind.stdio;
|
|
let args = [];
|
|
let options = node.options || Object.create(null);
|
|
let runtime = node.runtime || process.execPath;
|
|
if (options.execArgv)
|
|
options.execArgv.forEach(element => args.push(element));
|
|
if (transport != TransportKind.ipc)
|
|
args.push(node.module);
|
|
if (node.args)
|
|
node.args.forEach(element => args.push(element));
|
|
let execOptions = Object.create(null);
|
|
execOptions.cwd = serverWorkingDir;
|
|
execOptions.env = getEnvironment(options.env);
|
|
let pipeName;
|
|
if (transport === TransportKind.ipc) {
|
|
execOptions.stdio = [null, null, null];
|
|
args.push('--node-ipc');
|
|
}
|
|
else if (transport === TransportKind.stdio) {
|
|
args.push('--stdio');
|
|
}
|
|
else if (transport === TransportKind.pipe) {
|
|
pipeName = vscode_languageserver_protocol_1.generateRandomPipeName();
|
|
args.push(`--pipe=${pipeName}`);
|
|
}
|
|
else if (Transport.isSocket(transport)) {
|
|
args.push(`--socket=${transport.port}`);
|
|
}
|
|
args.push(`--clientProcessId=${process.pid.toString()}`);
|
|
if (transport === TransportKind.ipc) {
|
|
let forkOptions = {
|
|
cwd: serverWorkingDir,
|
|
env: getEnvironment(options.env),
|
|
stdio: [null, null, null, 'ipc'],
|
|
execPath: runtime,
|
|
execArgv: options.execArgv || [],
|
|
};
|
|
let serverProcess = child_process_1.default.fork(node.module, args, forkOptions);
|
|
if (!serverProcess || !serverProcess.pid) {
|
|
throw new Error(`Launching server ${node.module} failed.`);
|
|
}
|
|
logger.info(`${this.id} started with ${serverProcess.pid}`);
|
|
this._serverProcess = serverProcess;
|
|
serverProcess.stdout.on('data', data => this.appendOutput(data, encoding));
|
|
serverProcess.stderr.on('data', data => this.appendOutput(data, encoding));
|
|
return {
|
|
reader: new vscode_languageserver_protocol_1.IPCMessageReader(serverProcess),
|
|
writer: new vscode_languageserver_protocol_1.IPCMessageWriter(serverProcess)
|
|
};
|
|
}
|
|
else if (transport === TransportKind.stdio) {
|
|
let serverProcess = child_process_1.default.spawn(runtime, args, execOptions);
|
|
if (!serverProcess || !serverProcess.pid) {
|
|
throw new Error(`Launching server ${node.module} failed.`);
|
|
}
|
|
logger.info(`${this.id} started with ${serverProcess.pid}`);
|
|
this._serverProcess = serverProcess;
|
|
serverProcess.stderr.on('data', data => this.appendOutput(data, encoding));
|
|
return {
|
|
reader: new vscode_languageserver_protocol_1.StreamMessageReader(serverProcess.stdout),
|
|
writer: new vscode_languageserver_protocol_1.StreamMessageWriter(serverProcess.stdin)
|
|
};
|
|
}
|
|
else if (transport == TransportKind.pipe) {
|
|
let transport = await Promise.resolve(vscode_languageserver_protocol_1.createClientPipeTransport(pipeName));
|
|
let process = child_process_1.default.spawn(runtime, args, execOptions);
|
|
if (!process || !process.pid) {
|
|
throw new Error(`Launching server ${node.module} failed.`);
|
|
}
|
|
logger.info(`${this.id} started with ${process.pid}`);
|
|
this._serverProcess = process;
|
|
process.stderr.on('data', data => this.appendOutput(data, encoding));
|
|
process.stdout.on('data', data => this.appendOutput(data, encoding));
|
|
let protocol = await Promise.resolve(transport.onConnected());
|
|
return { reader: protocol[0], writer: protocol[1] };
|
|
}
|
|
else if (Transport.isSocket(node.transport)) {
|
|
let transport = await Promise.resolve(vscode_languageserver_protocol_1.createClientSocketTransport(node.transport.port));
|
|
let process = child_process_1.default.spawn(runtime, args, execOptions);
|
|
if (!process || !process.pid) {
|
|
throw new Error(`Launching server ${node.module} failed.`);
|
|
}
|
|
logger.info(`${this.id} started with ${process.pid}`);
|
|
this._serverProcess = process;
|
|
process.stderr.on('data', data => this.appendOutput(data, encoding));
|
|
process.stdout.on('data', data => this.appendOutput(data, encoding));
|
|
let protocol = await Promise.resolve(transport.onConnected());
|
|
return { reader: protocol[0], writer: protocol[1] };
|
|
}
|
|
}
|
|
else if (Executable.is(json) && json.command) {
|
|
let command = json;
|
|
let args = command.args || [];
|
|
let options = Object.assign({}, command.options);
|
|
options.env = options.env ? Object.assign(options.env, process.env) : process.env;
|
|
options.cwd = options.cwd || serverWorkingDir;
|
|
let cmd = json.command;
|
|
if (cmd.startsWith('~')) {
|
|
cmd = os_1.default.homedir() + cmd.slice(1);
|
|
}
|
|
if (cmd.indexOf('$') !== -1) {
|
|
cmd = string_1.resolveVariables(cmd, { workspaceFolder: workspace_1.default.rootPath });
|
|
}
|
|
if (path_1.default.isAbsolute(cmd) && !fs_1.default.existsSync(cmd)) {
|
|
logger.info(`${cmd} of ${this.id} not exists`);
|
|
return;
|
|
}
|
|
try {
|
|
which_1.default.sync(cmd);
|
|
}
|
|
catch (e) {
|
|
throw new Error(`Command "${cmd}" of ${this.id} is not executable: ${e}`);
|
|
}
|
|
let serverProcess = child_process_1.default.spawn(cmd, args, options);
|
|
if (!serverProcess || !serverProcess.pid) {
|
|
throw new Error(`Launching server using command ${command.command} failed.`);
|
|
}
|
|
logger.info(`${this.id} started with ${serverProcess.pid}`);
|
|
serverProcess.on('exit', code => {
|
|
if (code != 0)
|
|
this.error(`${command.command} exited with code: ${code}`);
|
|
});
|
|
serverProcess.stderr.on('data', data => this.appendOutput(data, encoding));
|
|
this._serverProcess = serverProcess;
|
|
this._isDetached = !!options.detached;
|
|
return {
|
|
reader: new vscode_languageserver_protocol_1.StreamMessageReader(serverProcess.stdout),
|
|
writer: new vscode_languageserver_protocol_1.StreamMessageWriter(serverProcess.stdin)
|
|
};
|
|
}
|
|
throw new Error(`Unsupported server configuration ` + JSON.stringify(server, null, 4));
|
|
}
|
|
registerProposedFeatures() {
|
|
this.registerFeatures(ProposedFeatures.createAll(this));
|
|
}
|
|
registerBuiltinFeatures() {
|
|
super.registerBuiltinFeatures();
|
|
this.registerFeature(new configuration_1.ConfigurationFeature(this));
|
|
this.registerFeature(new typeDefinition_1.TypeDefinitionFeature(this));
|
|
this.registerFeature(new implementation_1.ImplementationFeature(this));
|
|
this.registerFeature(new declaration_1.DeclarationFeature(this));
|
|
this.registerFeature(new colorProvider_1.ColorProviderFeature(this));
|
|
this.registerFeature(new foldingRange_1.FoldingRangeFeature(this));
|
|
if (!this.clientOptions.disableWorkspaceFolders) {
|
|
this.registerFeature(new workspaceFolders_1.WorkspaceFoldersFeature(this));
|
|
}
|
|
}
|
|
_getServerWorkingDir(options) {
|
|
let cwd = options && options.cwd;
|
|
if (cwd && !path_1.default.isAbsolute(cwd))
|
|
cwd = path_1.default.join(workspace_1.default.cwd, cwd);
|
|
if (!cwd)
|
|
cwd = workspace_1.default.cwd;
|
|
if (cwd) {
|
|
// make sure the folder exists otherwise creating the process will fail
|
|
return new Promise(s => {
|
|
fs_1.default.lstat(cwd, (err, stats) => {
|
|
s(!err && stats.isDirectory() ? cwd : undefined);
|
|
});
|
|
});
|
|
}
|
|
return Promise.resolve(undefined);
|
|
}
|
|
appendOutput(data, encoding) {
|
|
let msg = Is.string(data) ? data : data.toString(encoding);
|
|
if (global.hasOwnProperty('__TEST__')) {
|
|
console.log(msg); // tslint:disable-line
|
|
return;
|
|
}
|
|
if (process.env.NVIM_COC_LOG_LEVEL == 'debug') {
|
|
logger.debug(`[${this.id}]`, msg);
|
|
}
|
|
this.outputChannel.append(msg.endsWith('\n') ? msg : msg + '\n');
|
|
}
|
|
}
|
|
exports.LanguageClient = LanguageClient;
|
|
class SettingMonitor {
|
|
constructor(_client, _setting) {
|
|
this._client = _client;
|
|
this._setting = _setting;
|
|
this._listeners = [];
|
|
}
|
|
start() {
|
|
workspace_1.default.onDidChangeConfiguration(e => {
|
|
if (e.affectsConfiguration(this._setting)) {
|
|
this.onDidChangeConfiguration();
|
|
}
|
|
}, null, this._listeners);
|
|
this.onDidChangeConfiguration();
|
|
return {
|
|
dispose: () => {
|
|
util_1.disposeAll(this._listeners);
|
|
if (this._client.needsStop()) {
|
|
this._client.stop();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
onDidChangeConfiguration() {
|
|
let index = this._setting.indexOf('.');
|
|
let primary = index >= 0 ? this._setting.substr(0, index) : this._setting;
|
|
let rest = index >= 0 ? this._setting.substr(index + 1) : undefined;
|
|
let enabled = rest
|
|
? workspace_1.default.getConfiguration(primary).get(rest, true)
|
|
: workspace_1.default.getConfiguration(primary);
|
|
if (enabled && this._client.needsStart()) {
|
|
this._client.start();
|
|
}
|
|
else if (!enabled && this._client.needsStop()) {
|
|
this._client.stop();
|
|
}
|
|
}
|
|
}
|
|
exports.SettingMonitor = SettingMonitor;
|
|
// Exporting proposed protocol.
|
|
var ProposedFeatures;
|
|
(function (ProposedFeatures) {
|
|
function createAll(_client) {
|
|
let result = [];
|
|
return result;
|
|
}
|
|
ProposedFeatures.createAll = createAll;
|
|
})(ProposedFeatures = exports.ProposedFeatures || (exports.ProposedFeatures = {}));
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
/* 353 */
|
|
/***/ (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.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
/*tslint:disable*/
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const commands_1 = tslib_1.__importDefault(__webpack_require__(232));
|
|
const languages_1 = tslib_1.__importDefault(__webpack_require__(315));
|
|
const fs_1 = __webpack_require__(200);
|
|
const Is = tslib_1.__importStar(__webpack_require__(191));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const async_1 = __webpack_require__(354);
|
|
const cv = tslib_1.__importStar(__webpack_require__(355));
|
|
const UUID = tslib_1.__importStar(__webpack_require__(356));
|
|
const lodash_1 = __webpack_require__(312);
|
|
const logger = __webpack_require__(186)('language-client-client');
|
|
class ConsoleLogger {
|
|
error(message) {
|
|
logger.error(message);
|
|
}
|
|
warn(message) {
|
|
logger.warn(message);
|
|
}
|
|
info(message) {
|
|
logger.info(message);
|
|
}
|
|
log(message) {
|
|
logger.log(message);
|
|
}
|
|
}
|
|
function createConnection(input, output, errorHandler, closeHandler) {
|
|
let logger = new ConsoleLogger();
|
|
let connection = vscode_languageserver_protocol_1.createProtocolConnection(input, output, logger);
|
|
connection.onError(data => {
|
|
errorHandler(data[0], data[1], data[2]);
|
|
});
|
|
connection.onClose(closeHandler);
|
|
let result = {
|
|
listen: () => connection.listen(),
|
|
sendRequest: (type, ...params) => connection.sendRequest(Is.string(type) ? type : type.method, ...params),
|
|
onRequest: (type, handler) => connection.onRequest(Is.string(type) ? type : type.method, handler),
|
|
sendNotification: (type, params) => connection.sendNotification(Is.string(type) ? type : type.method, params),
|
|
onNotification: (type, handler) => connection.onNotification(Is.string(type) ? type : type.method, handler),
|
|
trace: (value, tracer, sendNotificationOrTraceOptions) => {
|
|
const defaultTraceOptions = {
|
|
sendNotification: false,
|
|
traceFormat: vscode_languageserver_protocol_1.TraceFormat.Text
|
|
};
|
|
if (sendNotificationOrTraceOptions === void 0) {
|
|
connection.trace(value, tracer, defaultTraceOptions);
|
|
}
|
|
else if (Is.boolean(sendNotificationOrTraceOptions)) {
|
|
connection.trace(value, tracer, sendNotificationOrTraceOptions);
|
|
}
|
|
else {
|
|
connection.trace(value, tracer, sendNotificationOrTraceOptions);
|
|
}
|
|
},
|
|
initialize: (params) => connection.sendRequest(vscode_languageserver_protocol_1.InitializeRequest.type, params),
|
|
shutdown: () => connection.sendRequest(vscode_languageserver_protocol_1.ShutdownRequest.type, undefined),
|
|
exit: () => connection.sendNotification(vscode_languageserver_protocol_1.ExitNotification.type),
|
|
onLogMessage: (handler) => connection.onNotification(vscode_languageserver_protocol_1.LogMessageNotification.type, handler),
|
|
onShowMessage: (handler) => connection.onNotification(vscode_languageserver_protocol_1.ShowMessageNotification.type, handler),
|
|
onTelemetry: (handler) => connection.onNotification(vscode_languageserver_protocol_1.TelemetryEventNotification.type, handler),
|
|
didChangeConfiguration: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidChangeConfigurationNotification.type, params),
|
|
didChangeWatchedFiles: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidChangeWatchedFilesNotification.type, params),
|
|
didOpenTextDocument: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidOpenTextDocumentNotification.type, params),
|
|
didChangeTextDocument: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, params),
|
|
didCloseTextDocument: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidCloseTextDocumentNotification.type, params),
|
|
didSaveTextDocument: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidSaveTextDocumentNotification.type, params),
|
|
onDiagnostics: (handler) => connection.onNotification(vscode_languageserver_protocol_1.PublishDiagnosticsNotification.type, handler),
|
|
dispose: () => connection.dispose()
|
|
};
|
|
return result;
|
|
}
|
|
/**
|
|
* An action to be performed when the connection is producing errors.
|
|
*/
|
|
var ErrorAction;
|
|
(function (ErrorAction) {
|
|
/**
|
|
* Continue running the server.
|
|
*/
|
|
ErrorAction[ErrorAction["Continue"] = 1] = "Continue";
|
|
/**
|
|
* Shutdown the server.
|
|
*/
|
|
ErrorAction[ErrorAction["Shutdown"] = 2] = "Shutdown";
|
|
})(ErrorAction = exports.ErrorAction || (exports.ErrorAction = {}));
|
|
/**
|
|
* An action to be performed when the connection to a server got closed.
|
|
*/
|
|
var CloseAction;
|
|
(function (CloseAction) {
|
|
/**
|
|
* Don't restart the server. The connection stays closed.
|
|
*/
|
|
CloseAction[CloseAction["DoNotRestart"] = 1] = "DoNotRestart";
|
|
/**
|
|
* Restart the server.
|
|
*/
|
|
CloseAction[CloseAction["Restart"] = 2] = "Restart";
|
|
})(CloseAction = exports.CloseAction || (exports.CloseAction = {}));
|
|
class DefaultErrorHandler {
|
|
constructor(name) {
|
|
this.name = name;
|
|
this.restarts = [];
|
|
}
|
|
error(_error, _message, count) {
|
|
if (count && count <= 3) {
|
|
return ErrorAction.Continue;
|
|
}
|
|
return ErrorAction.Shutdown;
|
|
}
|
|
closed() {
|
|
this.restarts.push(Date.now());
|
|
if (this.restarts.length < 5) {
|
|
return CloseAction.Restart;
|
|
}
|
|
else {
|
|
let diff = this.restarts[this.restarts.length - 1] - this.restarts[0];
|
|
if (diff <= 3 * 60 * 1000) {
|
|
logger.error(`The ${this.name} server crashed 5 times in the last 3 minutes. The server will not be restarted.`);
|
|
return CloseAction.DoNotRestart;
|
|
}
|
|
else {
|
|
this.restarts.shift();
|
|
return CloseAction.Restart;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
var RevealOutputChannelOn;
|
|
(function (RevealOutputChannelOn) {
|
|
RevealOutputChannelOn[RevealOutputChannelOn["Info"] = 1] = "Info";
|
|
RevealOutputChannelOn[RevealOutputChannelOn["Warn"] = 2] = "Warn";
|
|
RevealOutputChannelOn[RevealOutputChannelOn["Error"] = 3] = "Error";
|
|
RevealOutputChannelOn[RevealOutputChannelOn["Never"] = 4] = "Never";
|
|
})(RevealOutputChannelOn = exports.RevealOutputChannelOn || (exports.RevealOutputChannelOn = {}));
|
|
var State;
|
|
(function (State) {
|
|
State[State["Stopped"] = 1] = "Stopped";
|
|
State[State["Running"] = 2] = "Running";
|
|
State[State["Starting"] = 3] = "Starting";
|
|
})(State = exports.State || (exports.State = {}));
|
|
var ClientState;
|
|
(function (ClientState) {
|
|
ClientState[ClientState["Initial"] = 0] = "Initial";
|
|
ClientState[ClientState["Starting"] = 1] = "Starting";
|
|
ClientState[ClientState["StartFailed"] = 2] = "StartFailed";
|
|
ClientState[ClientState["Running"] = 3] = "Running";
|
|
ClientState[ClientState["Stopping"] = 4] = "Stopping";
|
|
ClientState[ClientState["Stopped"] = 5] = "Stopped";
|
|
})(ClientState = exports.ClientState || (exports.ClientState = {}));
|
|
const SupporedSymbolKinds = [
|
|
vscode_languageserver_protocol_1.SymbolKind.File,
|
|
vscode_languageserver_protocol_1.SymbolKind.Module,
|
|
vscode_languageserver_protocol_1.SymbolKind.Namespace,
|
|
vscode_languageserver_protocol_1.SymbolKind.Package,
|
|
vscode_languageserver_protocol_1.SymbolKind.Class,
|
|
vscode_languageserver_protocol_1.SymbolKind.Method,
|
|
vscode_languageserver_protocol_1.SymbolKind.Property,
|
|
vscode_languageserver_protocol_1.SymbolKind.Field,
|
|
vscode_languageserver_protocol_1.SymbolKind.Constructor,
|
|
vscode_languageserver_protocol_1.SymbolKind.Enum,
|
|
vscode_languageserver_protocol_1.SymbolKind.Interface,
|
|
vscode_languageserver_protocol_1.SymbolKind.Function,
|
|
vscode_languageserver_protocol_1.SymbolKind.Variable,
|
|
vscode_languageserver_protocol_1.SymbolKind.Constant,
|
|
vscode_languageserver_protocol_1.SymbolKind.String,
|
|
vscode_languageserver_protocol_1.SymbolKind.Number,
|
|
vscode_languageserver_protocol_1.SymbolKind.Boolean,
|
|
vscode_languageserver_protocol_1.SymbolKind.Array,
|
|
vscode_languageserver_protocol_1.SymbolKind.Object,
|
|
vscode_languageserver_protocol_1.SymbolKind.Key,
|
|
vscode_languageserver_protocol_1.SymbolKind.Null,
|
|
vscode_languageserver_protocol_1.SymbolKind.EnumMember,
|
|
vscode_languageserver_protocol_1.SymbolKind.Struct,
|
|
vscode_languageserver_protocol_1.SymbolKind.Event,
|
|
vscode_languageserver_protocol_1.SymbolKind.Operator,
|
|
vscode_languageserver_protocol_1.SymbolKind.TypeParameter
|
|
];
|
|
const SupportedCompletionItemKinds = [
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Text,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Method,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Function,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Constructor,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Field,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Variable,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Class,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Interface,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Module,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Property,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Unit,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Value,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Enum,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Keyword,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Snippet,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Color,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.File,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Reference,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Folder,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.EnumMember,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Constant,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Struct,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Event,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.Operator,
|
|
vscode_languageserver_protocol_1.CompletionItemKind.TypeParameter
|
|
];
|
|
function ensure(target, key) {
|
|
if (target[key] == null) {
|
|
target[key] = {};
|
|
}
|
|
return target[key];
|
|
}
|
|
var DynamicFeature;
|
|
(function (DynamicFeature) {
|
|
function is(value) {
|
|
let candidate = value;
|
|
return (candidate &&
|
|
Is.func(candidate.register) &&
|
|
Is.func(candidate.unregister) &&
|
|
Is.func(candidate.dispose) &&
|
|
candidate.messages != null);
|
|
}
|
|
DynamicFeature.is = is;
|
|
})(DynamicFeature || (DynamicFeature = {}));
|
|
class OnReady {
|
|
constructor(_resolve, _reject) {
|
|
this._resolve = _resolve;
|
|
this._reject = _reject;
|
|
this._used = false;
|
|
}
|
|
get isUsed() {
|
|
return this._used;
|
|
}
|
|
resolve() {
|
|
this._used = true;
|
|
this._resolve();
|
|
}
|
|
reject(error) {
|
|
this._used = true;
|
|
this._reject(error);
|
|
}
|
|
}
|
|
class DocumentNotifiactions {
|
|
constructor(_client, _event, _type, _middleware, _createParams, _selectorFilter) {
|
|
this._client = _client;
|
|
this._event = _event;
|
|
this._type = _type;
|
|
this._middleware = _middleware;
|
|
this._createParams = _createParams;
|
|
this._selectorFilter = _selectorFilter;
|
|
this._selectors = new Map();
|
|
}
|
|
static textDocumentFilter(selectors, textDocument) {
|
|
for (const selector of selectors) {
|
|
if (workspace_1.default.match(selector, textDocument) > 0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
register(_message, data) {
|
|
if (!data.registerOptions.documentSelector) {
|
|
return;
|
|
}
|
|
if (!this._listener) {
|
|
this._listener = this._event(this.callback, this);
|
|
}
|
|
this._selectors.set(data.id, data.registerOptions.documentSelector);
|
|
}
|
|
callback(data) {
|
|
if (!this._selectorFilter ||
|
|
this._selectorFilter(this._selectors.values(), data)) {
|
|
if (this._middleware) {
|
|
this._middleware(data, data => this._client.sendNotification(this._type, this._createParams(data)));
|
|
}
|
|
else {
|
|
this._client.sendNotification(this._type, this._createParams(data));
|
|
}
|
|
this.notificationSent(data);
|
|
}
|
|
}
|
|
notificationSent(_data) { }
|
|
unregister(id) {
|
|
this._selectors.delete(id);
|
|
if (this._selectors.size === 0 && this._listener) {
|
|
this._listener.dispose();
|
|
this._listener = undefined;
|
|
}
|
|
}
|
|
dispose() {
|
|
this._selectors.clear();
|
|
if (this._listener) {
|
|
this._listener.dispose();
|
|
this._listener = undefined;
|
|
}
|
|
}
|
|
}
|
|
class DidOpenTextDocumentFeature extends DocumentNotifiactions {
|
|
constructor(client, _syncedDocuments) {
|
|
super(client, workspace_1.default.onDidOpenTextDocument, vscode_languageserver_protocol_1.DidOpenTextDocumentNotification.type, client.clientOptions.middleware.didOpen, (textDocument) => {
|
|
return { textDocument: cv.convertToTextDocumentItem(textDocument) };
|
|
}, DocumentNotifiactions.textDocumentFilter);
|
|
this._syncedDocuments = _syncedDocuments;
|
|
}
|
|
get messages() {
|
|
return vscode_languageserver_protocol_1.DidOpenTextDocumentNotification.type;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'textDocument'), 'synchronization').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync;
|
|
if (documentSelector &&
|
|
textDocumentSyncOptions &&
|
|
textDocumentSyncOptions.openClose) {
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: { documentSelector: documentSelector }
|
|
});
|
|
}
|
|
}
|
|
register(message, data) {
|
|
super.register(message, data);
|
|
if (!data.registerOptions.documentSelector) {
|
|
return;
|
|
}
|
|
let documentSelector = data.registerOptions.documentSelector;
|
|
workspace_1.default.textDocuments.forEach(textDocument => {
|
|
let uri = textDocument.uri.toString();
|
|
if (this._syncedDocuments.has(uri)) {
|
|
return;
|
|
}
|
|
if (workspace_1.default.match(documentSelector, textDocument) > 0) {
|
|
let middleware = this._client.clientOptions.middleware;
|
|
let didOpen = (textDocument) => {
|
|
this._client.sendNotification(this._type, this._createParams(textDocument));
|
|
};
|
|
if (middleware.didOpen) {
|
|
middleware.didOpen(textDocument, didOpen);
|
|
}
|
|
else {
|
|
didOpen(textDocument);
|
|
}
|
|
this._syncedDocuments.set(uri, textDocument);
|
|
}
|
|
});
|
|
}
|
|
notificationSent(textDocument) {
|
|
super.notificationSent(textDocument);
|
|
this._syncedDocuments.set(textDocument.uri.toString(), textDocument);
|
|
}
|
|
}
|
|
class DidCloseTextDocumentFeature extends DocumentNotifiactions {
|
|
constructor(client, _syncedDocuments) {
|
|
super(client, workspace_1.default.onDidCloseTextDocument, vscode_languageserver_protocol_1.DidCloseTextDocumentNotification.type, client.clientOptions.middleware.didClose, (textDocument) => cv.asCloseTextDocumentParams(textDocument), DocumentNotifiactions.textDocumentFilter);
|
|
this._syncedDocuments = _syncedDocuments;
|
|
}
|
|
get messages() {
|
|
return vscode_languageserver_protocol_1.DidCloseTextDocumentNotification.type;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'textDocument'), 'synchronization').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync;
|
|
if (documentSelector &&
|
|
textDocumentSyncOptions &&
|
|
textDocumentSyncOptions.openClose) {
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: { documentSelector: documentSelector }
|
|
});
|
|
}
|
|
}
|
|
notificationSent(textDocument) {
|
|
super.notificationSent(textDocument);
|
|
this._syncedDocuments.delete(textDocument.uri.toString());
|
|
}
|
|
unregister(id) {
|
|
let selector = this._selectors.get(id);
|
|
// The super call removed the selector from the map
|
|
// of selectors.
|
|
super.unregister(id);
|
|
let selectors = this._selectors.values();
|
|
this._syncedDocuments.forEach(textDocument => {
|
|
if (workspace_1.default.match(selector, textDocument) > 0 &&
|
|
!this._selectorFilter(selectors, textDocument)) {
|
|
let middleware = this._client.clientOptions.middleware;
|
|
let didClose = (textDocument) => {
|
|
this._client.sendNotification(this._type, this._createParams(textDocument));
|
|
};
|
|
this._syncedDocuments.delete(textDocument.uri.toString());
|
|
if (middleware.didClose) {
|
|
middleware.didClose(textDocument, didClose);
|
|
}
|
|
else {
|
|
didClose(textDocument);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
class DidChangeTextDocumentFeature {
|
|
constructor(_client) {
|
|
this._client = _client;
|
|
this._changeData = new Map();
|
|
}
|
|
get messages() {
|
|
return vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'textDocument'), 'synchronization').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync;
|
|
if (documentSelector &&
|
|
textDocumentSyncOptions &&
|
|
textDocumentSyncOptions.change != null &&
|
|
textDocumentSyncOptions.change !== vscode_languageserver_protocol_1.TextDocumentSyncKind.None) {
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector }, { syncKind: textDocumentSyncOptions.change })
|
|
});
|
|
}
|
|
}
|
|
register(_message, data) {
|
|
if (!data.registerOptions.documentSelector) {
|
|
return;
|
|
}
|
|
if (!this._listener) {
|
|
this._listener = workspace_1.default.onDidChangeTextDocument(this.callback, this);
|
|
}
|
|
this._changeData.set(data.id, {
|
|
documentSelector: data.registerOptions.documentSelector,
|
|
syncKind: data.registerOptions.syncKind
|
|
});
|
|
}
|
|
callback(event) {
|
|
// Text document changes are send for dirty changes as well. We don't
|
|
// have dirty / undirty events in the LSP so we ignore content changes
|
|
// with length zero.
|
|
if (event.contentChanges.length === 0) {
|
|
return;
|
|
}
|
|
let doc = workspace_1.default.getDocument(event.textDocument.uri);
|
|
if (!doc)
|
|
return;
|
|
let { textDocument } = doc;
|
|
for (const changeData of this._changeData.values()) {
|
|
if (workspace_1.default.match(changeData.documentSelector, textDocument) > 0) {
|
|
let middleware = this._client.clientOptions.middleware;
|
|
if (changeData.syncKind === vscode_languageserver_protocol_1.TextDocumentSyncKind.Incremental) {
|
|
if (middleware.didChange) {
|
|
middleware.didChange(event, () => this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, lodash_1.omit(event, ['bufnr', 'original'])));
|
|
}
|
|
else {
|
|
this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, lodash_1.omit(event, ['bufnr', 'original']));
|
|
}
|
|
}
|
|
else if (changeData.syncKind === vscode_languageserver_protocol_1.TextDocumentSyncKind.Full) {
|
|
let didChange = event => {
|
|
let { textDocument } = workspace_1.default.getDocument(event.textDocument.uri);
|
|
this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, cv.asChangeTextDocumentParams(textDocument));
|
|
};
|
|
if (middleware.didChange) {
|
|
middleware.didChange(event, didChange);
|
|
}
|
|
else {
|
|
didChange(event);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
unregister(id) {
|
|
this._changeData.delete(id);
|
|
if (this._changeData.size === 0 && this._listener) {
|
|
this._listener.dispose();
|
|
this._listener = undefined;
|
|
}
|
|
}
|
|
dispose() {
|
|
this._changeData.clear();
|
|
if (this._listener) {
|
|
this._listener.dispose();
|
|
this._listener = undefined;
|
|
}
|
|
}
|
|
}
|
|
class WillSaveFeature extends DocumentNotifiactions {
|
|
constructor(client) {
|
|
super(client, workspace_1.default.onWillSaveTextDocument, vscode_languageserver_protocol_1.WillSaveTextDocumentNotification.type, client.clientOptions.middleware.willSave, willSaveEvent => cv.asWillSaveTextDocumentParams(willSaveEvent), (selectors, willSaveEvent) => DocumentNotifiactions.textDocumentFilter(selectors, willSaveEvent.document));
|
|
}
|
|
get messages() {
|
|
return vscode_languageserver_protocol_1.WillSaveTextDocumentNotification.type;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
let value = ensure(ensure(capabilities, 'textDocument'), 'synchronization');
|
|
value.willSave = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync;
|
|
if (documentSelector &&
|
|
textDocumentSyncOptions &&
|
|
textDocumentSyncOptions.willSave) {
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: { documentSelector: documentSelector }
|
|
});
|
|
}
|
|
}
|
|
}
|
|
class WillSaveWaitUntilFeature {
|
|
constructor(_client) {
|
|
this._client = _client;
|
|
this._selectors = new Map();
|
|
}
|
|
get messages() {
|
|
return vscode_languageserver_protocol_1.WillSaveTextDocumentWaitUntilRequest.type;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
let value = ensure(ensure(capabilities, 'textDocument'), 'synchronization');
|
|
value.willSaveWaitUntil = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync;
|
|
if (documentSelector &&
|
|
textDocumentSyncOptions &&
|
|
textDocumentSyncOptions.willSaveWaitUntil) {
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: { documentSelector: documentSelector }
|
|
});
|
|
}
|
|
}
|
|
register(_message, data) {
|
|
if (!data.registerOptions.documentSelector) {
|
|
return;
|
|
}
|
|
if (!this._listener) {
|
|
this._listener = workspace_1.default.onWillSaveUntil(this.callback, this, this._client.id);
|
|
}
|
|
this._selectors.set(data.id, data.registerOptions.documentSelector);
|
|
}
|
|
callback(event) {
|
|
if (DocumentNotifiactions.textDocumentFilter(this._selectors.values(), event.document)) {
|
|
let middleware = this._client.clientOptions.middleware;
|
|
let willSaveWaitUntil = (event) => {
|
|
return this._client
|
|
.sendRequest(vscode_languageserver_protocol_1.WillSaveTextDocumentWaitUntilRequest.type, cv.asWillSaveTextDocumentParams(event))
|
|
.then(edits => {
|
|
return edits ? edits : [];
|
|
}, e => {
|
|
workspace_1.default.showMessage(`Error on willSaveWaitUntil: ${e}`, 'error');
|
|
logger.error(e);
|
|
return [];
|
|
});
|
|
};
|
|
event.waitUntil(middleware.willSaveWaitUntil
|
|
? middleware.willSaveWaitUntil(event, willSaveWaitUntil)
|
|
: willSaveWaitUntil(event));
|
|
}
|
|
}
|
|
unregister(id) {
|
|
this._selectors.delete(id);
|
|
if (this._selectors.size === 0 && this._listener) {
|
|
this._listener.dispose();
|
|
this._listener = undefined;
|
|
}
|
|
}
|
|
dispose() {
|
|
this._selectors.clear();
|
|
if (this._listener) {
|
|
this._listener.dispose();
|
|
this._listener = undefined;
|
|
}
|
|
}
|
|
}
|
|
class DidSaveTextDocumentFeature extends DocumentNotifiactions {
|
|
constructor(client) {
|
|
super(client, workspace_1.default.onDidSaveTextDocument, vscode_languageserver_protocol_1.DidSaveTextDocumentNotification.type, client.clientOptions.middleware.didSave, textDocument => cv.asSaveTextDocumentParams(textDocument, this._includeText), DocumentNotifiactions.textDocumentFilter);
|
|
}
|
|
get messages() {
|
|
return vscode_languageserver_protocol_1.DidSaveTextDocumentNotification.type;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'textDocument'), 'synchronization').didSave = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync;
|
|
if (documentSelector &&
|
|
textDocumentSyncOptions &&
|
|
textDocumentSyncOptions.save) {
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector }, { includeText: !!textDocumentSyncOptions.save.includeText })
|
|
});
|
|
}
|
|
}
|
|
register(method, data) {
|
|
this._includeText = !!data.registerOptions.includeText;
|
|
super.register(method, data);
|
|
}
|
|
}
|
|
class FileSystemWatcherFeature {
|
|
constructor(_client, _notifyFileEvent) {
|
|
this._notifyFileEvent = _notifyFileEvent;
|
|
this._watchers = new Map();
|
|
}
|
|
get messages() {
|
|
return vscode_languageserver_protocol_1.DidChangeWatchedFilesNotification.type;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'workspace'), 'didChangeWatchedFiles').dynamicRegistration = true;
|
|
}
|
|
initialize(_capabilities, _documentSelector) { }
|
|
register(_method, data) {
|
|
if (!Array.isArray(data.registerOptions.watchers)) {
|
|
return;
|
|
}
|
|
let disposables = [];
|
|
for (let watcher of data.registerOptions.watchers) {
|
|
if (!Is.string(watcher.globPattern)) {
|
|
continue;
|
|
}
|
|
let watchCreate = true, watchChange = true, watchDelete = true;
|
|
if (watcher.kind != null) {
|
|
watchCreate = (watcher.kind & vscode_languageserver_protocol_1.WatchKind.Create) !== 0;
|
|
watchChange = (watcher.kind & vscode_languageserver_protocol_1.WatchKind.Change) != 0;
|
|
watchDelete = (watcher.kind & vscode_languageserver_protocol_1.WatchKind.Delete) != 0;
|
|
}
|
|
let fileSystemWatcher = workspace_1.default.createFileSystemWatcher(watcher.globPattern, !watchCreate, !watchChange, !watchDelete);
|
|
this.hookListeners(fileSystemWatcher, watchCreate, watchChange, watchDelete, disposables);
|
|
disposables.push(fileSystemWatcher);
|
|
}
|
|
this._watchers.set(data.id, disposables);
|
|
}
|
|
registerRaw(id, fileSystemWatchers) {
|
|
let disposables = [];
|
|
for (let fileSystemWatcher of fileSystemWatchers) {
|
|
disposables.push(fileSystemWatcher);
|
|
this.hookListeners(fileSystemWatcher, true, true, true, disposables);
|
|
}
|
|
this._watchers.set(id, disposables);
|
|
}
|
|
hookListeners(fileSystemWatcher, watchCreate, watchChange, watchDelete, listeners) {
|
|
if (watchCreate) {
|
|
fileSystemWatcher.onDidCreate(resource => this._notifyFileEvent({
|
|
uri: cv.asUri(resource),
|
|
type: vscode_languageserver_protocol_1.FileChangeType.Created
|
|
}), null, listeners);
|
|
}
|
|
if (watchChange) {
|
|
fileSystemWatcher.onDidChange(resource => this._notifyFileEvent({
|
|
uri: cv.asUri(resource),
|
|
type: vscode_languageserver_protocol_1.FileChangeType.Changed
|
|
}), null, listeners);
|
|
}
|
|
if (watchDelete) {
|
|
fileSystemWatcher.onDidDelete(resource => this._notifyFileEvent({
|
|
uri: cv.asUri(resource),
|
|
type: vscode_languageserver_protocol_1.FileChangeType.Deleted
|
|
}), null, listeners);
|
|
}
|
|
}
|
|
unregister(id) {
|
|
let disposables = this._watchers.get(id);
|
|
if (disposables) {
|
|
for (let disposable of disposables) {
|
|
disposable.dispose();
|
|
}
|
|
}
|
|
}
|
|
dispose() {
|
|
this._watchers.forEach(disposables => {
|
|
for (let disposable of disposables) {
|
|
disposable.dispose();
|
|
}
|
|
});
|
|
this._watchers.clear();
|
|
}
|
|
}
|
|
class TextDocumentFeature {
|
|
constructor(_client, _message) {
|
|
this._client = _client;
|
|
this._message = _message;
|
|
this._providers = new Map();
|
|
}
|
|
get messages() {
|
|
return this._message;
|
|
}
|
|
register(message, data) {
|
|
if (message.method !== this.messages.method) {
|
|
throw new Error(`Register called on wrong feature. Requested ${message.method} but reached feature ${this.messages.method}`);
|
|
}
|
|
if (!data.registerOptions.documentSelector) {
|
|
return;
|
|
}
|
|
let provider = this.registerLanguageProvider(data.registerOptions);
|
|
if (provider) {
|
|
this._providers.set(data.id, provider);
|
|
}
|
|
}
|
|
unregister(id) {
|
|
let provider = this._providers.get(id);
|
|
if (provider) {
|
|
provider.dispose();
|
|
}
|
|
}
|
|
dispose() {
|
|
this._providers.forEach(value => {
|
|
value.dispose();
|
|
});
|
|
this._providers.clear();
|
|
}
|
|
}
|
|
exports.TextDocumentFeature = TextDocumentFeature;
|
|
class WorkspaceFeature {
|
|
constructor(_client, _message) {
|
|
this._client = _client;
|
|
this._message = _message;
|
|
this._providers = new Map();
|
|
}
|
|
get messages() {
|
|
return this._message;
|
|
}
|
|
register(message, data) {
|
|
if (message.method !== this.messages.method) {
|
|
throw new Error(`Register called on wrong feature. Requested ${message.method} but reached feature ${this.messages.method}`);
|
|
}
|
|
let provider = this.registerLanguageProvider(data.registerOptions);
|
|
if (provider) {
|
|
this._providers.set(data.id, provider);
|
|
}
|
|
}
|
|
unregister(id) {
|
|
let provider = this._providers.get(id);
|
|
if (provider) {
|
|
provider.dispose();
|
|
}
|
|
}
|
|
dispose() {
|
|
this._providers.forEach(value => {
|
|
value.dispose();
|
|
});
|
|
this._providers.clear();
|
|
}
|
|
}
|
|
class CompletionItemFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.CompletionRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
let completion = ensure(ensure(capabilites, 'textDocument'), 'completion');
|
|
completion.dynamicRegistration = true;
|
|
completion.contextSupport = true;
|
|
completion.completionItem = {
|
|
snippetSupport: true,
|
|
commitCharactersSupport: true,
|
|
documentationFormat: [vscode_languageserver_protocol_1.MarkupKind.Markdown, vscode_languageserver_protocol_1.MarkupKind.PlainText],
|
|
deprecatedSupport: true,
|
|
preselectSupport: true
|
|
};
|
|
completion.completionItemKind = { valueSet: SupportedCompletionItemKinds };
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.completionProvider || !documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector }, capabilities.completionProvider)
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let triggerCharacters = options.triggerCharacters || [];
|
|
let client = this._client;
|
|
let provideCompletionItems = (document, position, context, token) => {
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.CompletionRequest.type, cv.asCompletionParams(document, position, context), token)
|
|
.then(result => {
|
|
// logger.debug('result', result)
|
|
return result;
|
|
}, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.CompletionRequest.type, error);
|
|
return Promise.resolve([]);
|
|
});
|
|
};
|
|
let resolveCompletionItem = (item, token) => {
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.CompletionResolveRequest.type, item, token)
|
|
.then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.CompletionResolveRequest.type, error);
|
|
return Promise.resolve(item);
|
|
});
|
|
};
|
|
let middleware = this._client.clientOptions.middleware;
|
|
let languageIds = cv.asLanguageIds(options.documentSelector);
|
|
return languages_1.default.registerCompletionItemProvider(this._client.id, 'LS', languageIds, {
|
|
provideCompletionItems: (document, position, token, context) => {
|
|
return middleware.provideCompletionItem
|
|
? middleware.provideCompletionItem(document, position, context, token, provideCompletionItems)
|
|
: provideCompletionItems(document, position, context, token);
|
|
},
|
|
resolveCompletionItem: options.resolveProvider
|
|
? (item, token) => {
|
|
return middleware.resolveCompletionItem
|
|
? middleware.resolveCompletionItem(item, token, resolveCompletionItem)
|
|
: resolveCompletionItem(item, token);
|
|
}
|
|
: undefined
|
|
}, triggerCharacters);
|
|
}
|
|
}
|
|
class HoverFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.HoverRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
const hoverCapability = ensure(ensure(capabilites, 'textDocument'), 'hover');
|
|
hoverCapability.dynamicRegistration = true;
|
|
hoverCapability.contentFormat = [vscode_languageserver_protocol_1.MarkupKind.Markdown, vscode_languageserver_protocol_1.MarkupKind.PlainText];
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.hoverProvider || !documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector })
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideHover = (document, position, token) => {
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.HoverRequest.type, cv.asTextDocumentPositionParams(document, position), token)
|
|
.then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.HoverRequest.type, error);
|
|
return Promise.resolve(null);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerHoverProvider(options.documentSelector, {
|
|
provideHover: (document, position, token) => {
|
|
return middleware.provideHover
|
|
? middleware.provideHover(document, position, token, provideHover)
|
|
: provideHover(document, position, token);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
class SignatureHelpFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.SignatureHelpRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
let config = ensure(ensure(capabilites, 'textDocument'), 'signatureHelp');
|
|
config.dynamicRegistration = true;
|
|
config.signatureInformation = {
|
|
documentationFormat: [vscode_languageserver_protocol_1.MarkupKind.Markdown, vscode_languageserver_protocol_1.MarkupKind.PlainText],
|
|
parameterInformation: {
|
|
labelOffsetSupport: true
|
|
}
|
|
};
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.signatureHelpProvider || !documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector }, capabilities.signatureHelpProvider)
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let providerSignatureHelp = (document, position, token) => {
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.SignatureHelpRequest.type, cv.asTextDocumentPositionParams(document, position), token)
|
|
.then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.SignatureHelpRequest.type, error);
|
|
return Promise.resolve(null);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
let triggerCharacters = options.triggerCharacters || [];
|
|
return languages_1.default.registerSignatureHelpProvider(options.documentSelector, {
|
|
provideSignatureHelp: (document, position, token) => {
|
|
return middleware.provideSignatureHelp
|
|
? middleware.provideSignatureHelp(document, position, token, providerSignatureHelp)
|
|
: providerSignatureHelp(document, position, token);
|
|
}
|
|
}, triggerCharacters);
|
|
}
|
|
}
|
|
class DefinitionFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DefinitionRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
let definitionSupport = ensure(ensure(capabilites, 'textDocument'), 'definition');
|
|
definitionSupport.dynamicRegistration = true;
|
|
// definitionSupport.linkSupport = true
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.definitionProvider || !documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector })
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideDefinition = (document, position, token) => {
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.DefinitionRequest.type, cv.asTextDocumentPositionParams(document, position), token)
|
|
.then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.DefinitionRequest.type, error);
|
|
return Promise.resolve(null);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerDefinitionProvider(options.documentSelector, {
|
|
provideDefinition: (document, position, token) => {
|
|
return middleware.provideDefinition
|
|
? middleware.provideDefinition(document, position, token, provideDefinition)
|
|
: provideDefinition(document, position, token);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
class ReferencesFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.ReferencesRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
ensure(ensure(capabilites, 'textDocument'), 'references').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.referencesProvider || !documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector })
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let providerReferences = (document, position, options, token) => {
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.ReferencesRequest.type, cv.asReferenceParams(document, position, options), token)
|
|
.then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.ReferencesRequest.type, error);
|
|
return Promise.resolve([]);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerReferencesProvider(options.documentSelector, {
|
|
provideReferences: (document, position, options, token) => {
|
|
return middleware.provideReferences
|
|
? middleware.provideReferences(document, position, options, token, providerReferences)
|
|
: providerReferences(document, position, options, token);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
class DocumentHighlightFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DocumentHighlightRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
ensure(ensure(capabilites, 'textDocument'), 'documentHighlight').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.documentHighlightProvider || !documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector })
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideDocumentHighlights = (document, position, token) => {
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.DocumentHighlightRequest.type, cv.asTextDocumentPositionParams(document, position), token)
|
|
.then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.DocumentHighlightRequest.type, error);
|
|
return Promise.resolve([]);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerDocumentHighlightProvider(options.documentSelector, {
|
|
provideDocumentHighlights: (document, position, token) => {
|
|
return middleware.provideDocumentHighlights
|
|
? middleware.provideDocumentHighlights(document, position, token, provideDocumentHighlights)
|
|
: provideDocumentHighlights(document, position, token);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
class DocumentSymbolFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DocumentSymbolRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
let symbolCapabilities = ensure(ensure(capabilites, 'textDocument'), 'documentSymbol');
|
|
symbolCapabilities.dynamicRegistration = true;
|
|
symbolCapabilities.symbolKind = {
|
|
valueSet: SupporedSymbolKinds
|
|
};
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.documentSymbolProvider || !documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector })
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideDocumentSymbols = (document, token) => {
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.DocumentSymbolRequest.type, cv.asDocumentSymbolParams(document), token)
|
|
.then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.DocumentSymbolRequest.type, error);
|
|
return Promise.resolve([]);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerDocumentSymbolProvider(options.documentSelector, {
|
|
provideDocumentSymbols: (document, token) => {
|
|
return middleware.provideDocumentSymbols
|
|
? middleware.provideDocumentSymbols(document, token, provideDocumentSymbols)
|
|
: provideDocumentSymbols(document, token);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
class WorkspaceSymbolFeature extends WorkspaceFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.WorkspaceSymbolRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
let symbolCapabilities = ensure(ensure(capabilites, 'workspace'), 'symbol');
|
|
symbolCapabilities.dynamicRegistration = true;
|
|
symbolCapabilities.symbolKind = {
|
|
valueSet: SupporedSymbolKinds
|
|
};
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.workspaceSymbolProvider) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector })
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideWorkspaceSymbols = (query, token) => {
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.WorkspaceSymbolRequest.type, { query }, token)
|
|
.then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.WorkspaceSymbolRequest.type, error);
|
|
return Promise.resolve([]);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerWorkspaceSymbolProvider(options.documentSelector, {
|
|
provideWorkspaceSymbols: (query, token) => {
|
|
return middleware.provideWorkspaceSymbols
|
|
? middleware.provideWorkspaceSymbols(query, token, provideWorkspaceSymbols)
|
|
: provideWorkspaceSymbols(query, token);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
class CodeActionFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.CodeActionRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
const cap = ensure(ensure(capabilites, 'textDocument'), 'codeAction');
|
|
cap.dynamicRegistration = true;
|
|
cap.codeActionLiteralSupport = {
|
|
codeActionKind: {
|
|
valueSet: [
|
|
'',
|
|
vscode_languageserver_protocol_1.CodeActionKind.QuickFix,
|
|
vscode_languageserver_protocol_1.CodeActionKind.Refactor,
|
|
vscode_languageserver_protocol_1.CodeActionKind.RefactorExtract,
|
|
vscode_languageserver_protocol_1.CodeActionKind.RefactorInline,
|
|
vscode_languageserver_protocol_1.CodeActionKind.RefactorRewrite,
|
|
vscode_languageserver_protocol_1.CodeActionKind.Source,
|
|
vscode_languageserver_protocol_1.CodeActionKind.SourceOrganizeImports
|
|
]
|
|
}
|
|
};
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.codeActionProvider || !documentSelector) {
|
|
return;
|
|
}
|
|
let codeActionKinds;
|
|
if (!Is.boolean(capabilities.codeActionProvider)) {
|
|
codeActionKinds = capabilities.codeActionProvider.codeActionKinds;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector, codeActionKinds })
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideCodeActions = (document, range, context, token) => {
|
|
let params = {
|
|
textDocument: {
|
|
uri: document.uri
|
|
},
|
|
range,
|
|
context,
|
|
};
|
|
return client.sendRequest(vscode_languageserver_protocol_1.CodeActionRequest.type, params, token).then(values => {
|
|
if (values == null)
|
|
return null;
|
|
return values;
|
|
}, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.CodeActionRequest.type, error);
|
|
return Promise.resolve([]);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerCodeActionProvider(options.documentSelector, {
|
|
provideCodeActions: (document, range, context, token) => {
|
|
return middleware.provideCodeActions
|
|
? middleware.provideCodeActions(document, range, context, token, provideCodeActions)
|
|
: provideCodeActions(document, range, context, token);
|
|
}
|
|
}, client.id, options.codeActionKinds);
|
|
}
|
|
}
|
|
class CodeLensFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.CodeLensRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
ensure(ensure(capabilites, 'textDocument'), 'codeLens').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.codeLensProvider || !documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector }, capabilities.codeLensProvider)
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideCodeLenses = (document, token) => {
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.CodeLensRequest.type, cv.asCodeLensParams(document), token).then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.CodeLensRequest.type, error);
|
|
return Promise.resolve([]);
|
|
});
|
|
};
|
|
let resolveCodeLens = (codeLens, token) => {
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.CodeLensResolveRequest.type, codeLens, token)
|
|
.then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.CodeLensResolveRequest.type, error);
|
|
return codeLens;
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerCodeLensProvider(options.documentSelector, {
|
|
provideCodeLenses: (document, token) => {
|
|
return middleware.provideCodeLenses
|
|
? middleware.provideCodeLenses(document, token, provideCodeLenses)
|
|
: provideCodeLenses(document, token);
|
|
},
|
|
resolveCodeLens: options.resolveProvider
|
|
? (codeLens, token) => {
|
|
return middleware.resolveCodeLens
|
|
? middleware.resolveCodeLens(codeLens, token, resolveCodeLens)
|
|
: resolveCodeLens(codeLens, token);
|
|
}
|
|
: undefined
|
|
});
|
|
}
|
|
}
|
|
class DocumentFormattingFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DocumentFormattingRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
ensure(ensure(capabilites, 'textDocument'), 'formatting').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.documentFormattingProvider || !documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector })
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideDocumentFormattingEdits = (document, options, token) => {
|
|
let params = {
|
|
textDocument: {
|
|
uri: document.uri
|
|
},
|
|
options
|
|
};
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.DocumentFormattingRequest.type, params, token)
|
|
.then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.DocumentFormattingRequest.type, error);
|
|
return Promise.resolve([]);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerDocumentFormatProvider(options.documentSelector, {
|
|
provideDocumentFormattingEdits: (document, options, token) => {
|
|
return middleware.provideDocumentFormattingEdits
|
|
? middleware.provideDocumentFormattingEdits(document, options, token, provideDocumentFormattingEdits)
|
|
: provideDocumentFormattingEdits(document, options, token);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
class DocumentRangeFormattingFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DocumentRangeFormattingRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
ensure(ensure(capabilites, 'textDocument'), 'rangeFormatting').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.documentRangeFormattingProvider || !documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector })
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideDocumentRangeFormattingEdits = (document, range, options, token) => {
|
|
let params = {
|
|
textDocument: {
|
|
uri: document.uri
|
|
},
|
|
range,
|
|
options,
|
|
};
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.DocumentRangeFormattingRequest.type, params, token)
|
|
.then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.DocumentRangeFormattingRequest.type, error);
|
|
return Promise.resolve([]);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerDocumentRangeFormatProvider(options.documentSelector, {
|
|
provideDocumentRangeFormattingEdits: (document, range, options, token) => {
|
|
return middleware.provideDocumentRangeFormattingEdits
|
|
? middleware.provideDocumentRangeFormattingEdits(document, range, options, token, provideDocumentRangeFormattingEdits)
|
|
: provideDocumentRangeFormattingEdits(document, range, options, token);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
class DocumentOnTypeFormattingFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DocumentOnTypeFormattingRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
ensure(ensure(capabilites, 'textDocument'), 'onTypeFormatting').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.documentOnTypeFormattingProvider || !documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector }, capabilities.documentOnTypeFormattingProvider)
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let moreTriggerCharacter = options.moreTriggerCharacter || [];
|
|
let provideOnTypeFormattingEdits = (document, position, ch, options, token) => {
|
|
let params = {
|
|
textDocument: cv.asVersionedTextDocumentIdentifier(document),
|
|
position,
|
|
ch,
|
|
options
|
|
};
|
|
return client.sendRequest(vscode_languageserver_protocol_1.DocumentOnTypeFormattingRequest.type, params, token).then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.DocumentOnTypeFormattingRequest.type, error);
|
|
return Promise.resolve([]);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
let characters = [options.firstTriggerCharacter, ...moreTriggerCharacter];
|
|
return languages_1.default.registerOnTypeFormattingEditProvider(options.documentSelector, {
|
|
provideOnTypeFormattingEdits: (document, position, ch, options, token) => {
|
|
return middleware.provideOnTypeFormattingEdits
|
|
? middleware.provideOnTypeFormattingEdits(document, position, ch, options, token, provideOnTypeFormattingEdits)
|
|
: provideOnTypeFormattingEdits(document, position, ch, options, token);
|
|
}
|
|
}, characters);
|
|
}
|
|
}
|
|
class RenameFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.RenameRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
let rename = ensure(ensure(capabilites, 'textDocument'), 'rename');
|
|
rename.dynamicRegistration = true;
|
|
rename.prepareSupport = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.renameProvider || !documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector }, capabilities.renameProvider || {})
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideRenameEdits = (document, position, newName, token) => {
|
|
let params = {
|
|
textDocument: {
|
|
uri: document.uri
|
|
},
|
|
position,
|
|
newName: newName
|
|
};
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.RenameRequest.type, params, token)
|
|
.then(res => res, (error) => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.RenameRequest.type, error);
|
|
return Promise.reject(new Error(error.message));
|
|
});
|
|
};
|
|
let prepareRename = (document, position, token) => {
|
|
let params = {
|
|
textDocument: cv.asTextDocumentIdentifier(document),
|
|
position
|
|
};
|
|
return client.sendRequest(vscode_languageserver_protocol_1.PrepareRenameRequest.type, params, token).then(result => {
|
|
return result;
|
|
}, (error) => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.PrepareRenameRequest.type, error);
|
|
return Promise.reject(new Error(error.message));
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerRenameProvider(options.documentSelector, {
|
|
provideRenameEdits: (document, position, newName, token) => {
|
|
return middleware.provideRenameEdits
|
|
? middleware.provideRenameEdits(document, position, newName, token, provideRenameEdits)
|
|
: provideRenameEdits(document, position, newName, token);
|
|
},
|
|
prepareRename: options.prepareProvider
|
|
? (document, position, token) => {
|
|
return middleware.prepareRename
|
|
? middleware.prepareRename(document, position, token, prepareRename)
|
|
: prepareRename(document, position, token);
|
|
} : undefined
|
|
});
|
|
}
|
|
}
|
|
class DocumentLinkFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DocumentLinkRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
ensure(ensure(capabilites, 'textDocument'), 'documentLink').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.documentLinkProvider || !documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector }, capabilities.documentLinkProvider)
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideDocumentLinks = (document, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.DocumentLinkRequest.type, {
|
|
textDocument: {
|
|
uri: document.uri
|
|
}
|
|
}, token).then(res => res, (error) => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.DocumentLinkRequest.type, error);
|
|
Promise.resolve(new Error(error.message));
|
|
});
|
|
};
|
|
let resolveDocumentLink = (link, token) => {
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.DocumentLinkResolveRequest.type, link, token)
|
|
.then(res => res, (error) => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.DocumentLinkResolveRequest.type, error);
|
|
Promise.resolve(new Error(error.message));
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerDocumentLinkProvider(options.documentSelector, {
|
|
provideDocumentLinks: (document, token) => {
|
|
return middleware.provideDocumentLinks
|
|
? middleware.provideDocumentLinks(document, token, provideDocumentLinks)
|
|
: provideDocumentLinks(document, token);
|
|
},
|
|
resolveDocumentLink: options.resolveProvider
|
|
? (link, token) => {
|
|
return middleware.resolveDocumentLink
|
|
? middleware.resolveDocumentLink(link, token, resolveDocumentLink)
|
|
: resolveDocumentLink(link, token);
|
|
}
|
|
: undefined
|
|
});
|
|
}
|
|
}
|
|
class ConfigurationFeature {
|
|
constructor(_client) {
|
|
this._client = _client;
|
|
this._listeners = new Map();
|
|
}
|
|
get messages() {
|
|
return vscode_languageserver_protocol_1.DidChangeConfigurationNotification.type;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'workspace'), 'didChangeConfiguration').dynamicRegistration = true;
|
|
}
|
|
initialize() {
|
|
let section = this._client.clientOptions.synchronize.configurationSection;
|
|
if (section != null) {
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: {
|
|
section: section
|
|
}
|
|
});
|
|
}
|
|
}
|
|
register(_message, data) {
|
|
let { section } = data.registerOptions;
|
|
let disposable = workspace_1.default.onDidChangeConfiguration(() => {
|
|
if (section != null) {
|
|
this.onDidChangeConfiguration(data.registerOptions.section);
|
|
}
|
|
});
|
|
this._listeners.set(data.id, disposable);
|
|
if (Is.string(section) && section.endsWith('.settings')) {
|
|
let settings = this.getConfiguredSettings(section);
|
|
if (!settings || Is.emptyObject(settings))
|
|
return;
|
|
}
|
|
if (section != null) {
|
|
this.onDidChangeConfiguration(data.registerOptions.section);
|
|
}
|
|
}
|
|
unregister(id) {
|
|
let disposable = this._listeners.get(id);
|
|
if (disposable) {
|
|
this._listeners.delete(id);
|
|
disposable.dispose();
|
|
}
|
|
}
|
|
dispose() {
|
|
for (let disposable of this._listeners.values()) {
|
|
disposable.dispose();
|
|
}
|
|
this._listeners.clear();
|
|
}
|
|
onDidChangeConfiguration(configurationSection) {
|
|
let sections;
|
|
if (Is.string(configurationSection)) {
|
|
sections = [configurationSection];
|
|
}
|
|
else {
|
|
sections = configurationSection;
|
|
}
|
|
let isConfigured = sections.length == 1 && /^languageserver\..+\.settings$/.test(sections[0]);
|
|
let didChangeConfiguration = (sections) => {
|
|
if (sections == null) {
|
|
this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeConfigurationNotification.type, {
|
|
settings: null
|
|
});
|
|
return;
|
|
}
|
|
this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeConfigurationNotification.type, {
|
|
settings: isConfigured ? this.getConfiguredSettings(sections[0]) : this.extractSettingsInformation(sections)
|
|
});
|
|
};
|
|
let middleware = this.getMiddleware();
|
|
middleware
|
|
? middleware(sections, didChangeConfiguration)
|
|
: didChangeConfiguration(sections);
|
|
}
|
|
getConfiguredSettings(key) {
|
|
let len = '.settings'.length;
|
|
let config = workspace_1.default.getConfiguration(key.slice(0, -len));
|
|
return config.get('settings', {});
|
|
}
|
|
extractSettingsInformation(keys) {
|
|
function ensurePath(config, path) {
|
|
let current = config;
|
|
for (let i = 0; i < path.length - 1; i++) {
|
|
let obj = current[path[i]];
|
|
if (!obj) {
|
|
obj = Object.create(null);
|
|
current[path[i]] = obj;
|
|
}
|
|
current = obj;
|
|
}
|
|
return current;
|
|
}
|
|
let result = Object.create(null);
|
|
for (let i = 0; i < keys.length; i++) {
|
|
let key = keys[i];
|
|
let index = key.indexOf('.');
|
|
let config = null;
|
|
if (index >= 0) {
|
|
config = workspace_1.default.getConfiguration(key.substr(0, index)).get(key.substr(index + 1));
|
|
}
|
|
else {
|
|
config = workspace_1.default.getConfiguration(key);
|
|
}
|
|
if (config) {
|
|
let path = keys[i].split('.');
|
|
ensurePath(result, path)[path[path.length - 1]] = config;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
getMiddleware() {
|
|
let middleware = this._client.clientOptions.middleware;
|
|
if (middleware.workspace && middleware.workspace.didChangeConfiguration) {
|
|
return middleware.workspace.didChangeConfiguration;
|
|
}
|
|
else {
|
|
return undefined;
|
|
}
|
|
}
|
|
}
|
|
class ExecuteCommandFeature {
|
|
constructor(_client) {
|
|
this._client = _client;
|
|
this._commands = new Map();
|
|
}
|
|
get messages() {
|
|
return vscode_languageserver_protocol_1.ExecuteCommandRequest.type;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'workspace'), 'executeCommand').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities) {
|
|
if (!capabilities.executeCommandProvider) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, capabilities.executeCommandProvider)
|
|
});
|
|
}
|
|
register(_message, data) {
|
|
let client = this._client;
|
|
if (data.registerOptions.commands) {
|
|
let disposables = [];
|
|
for (const command of data.registerOptions.commands) {
|
|
disposables.push(commands_1.default.registerCommand(command, (...args) => {
|
|
let params = {
|
|
command,
|
|
arguments: args
|
|
};
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.ExecuteCommandRequest.type, params)
|
|
.then(undefined, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.ExecuteCommandRequest.type, error);
|
|
});
|
|
}, null, true));
|
|
}
|
|
this._commands.set(data.id, disposables);
|
|
}
|
|
}
|
|
unregister(id) {
|
|
let disposables = this._commands.get(id);
|
|
if (disposables) {
|
|
disposables.forEach(disposable => disposable.dispose());
|
|
}
|
|
}
|
|
dispose() {
|
|
this._commands.forEach(value => {
|
|
value.forEach(disposable => disposable.dispose());
|
|
});
|
|
this._commands.clear();
|
|
}
|
|
}
|
|
var MessageTransports;
|
|
(function (MessageTransports) {
|
|
function is(value) {
|
|
let candidate = value;
|
|
return (candidate &&
|
|
vscode_languageserver_protocol_1.MessageReader.is(value.reader) &&
|
|
vscode_languageserver_protocol_1.MessageWriter.is(value.writer));
|
|
}
|
|
MessageTransports.is = is;
|
|
})(MessageTransports = exports.MessageTransports || (exports.MessageTransports = {}));
|
|
class BaseLanguageClient {
|
|
constructor(id, name, clientOptions) {
|
|
this._features = [];
|
|
this._method2Message = new Map();
|
|
this._dynamicFeatures = new Map();
|
|
this._id = id;
|
|
this._name = name;
|
|
clientOptions = clientOptions || {};
|
|
this._clientOptions = {
|
|
disableWorkspaceFolders: clientOptions.disableWorkspaceFolders,
|
|
disableDynamicRegister: clientOptions.disableDynamicRegister,
|
|
disableDiagnostics: clientOptions.disableDiagnostics,
|
|
disableCompletion: clientOptions.disableCompletion,
|
|
ignoredRootPaths: clientOptions.ignoredRootPaths,
|
|
documentSelector: clientOptions.documentSelector || [],
|
|
synchronize: clientOptions.synchronize || {},
|
|
diagnosticCollectionName: clientOptions.diagnosticCollectionName,
|
|
outputChannelName: clientOptions.outputChannelName || this._id,
|
|
revealOutputChannelOn: clientOptions.revealOutputChannelOn || RevealOutputChannelOn.Never,
|
|
stdioEncoding: clientOptions.stdioEncoding || 'utf8',
|
|
initializationOptions: clientOptions.initializationOptions,
|
|
initializationFailedHandler: clientOptions.initializationFailedHandler,
|
|
errorHandler: clientOptions.errorHandler || new DefaultErrorHandler(this._id),
|
|
middleware: clientOptions.middleware || {},
|
|
workspaceFolder: clientOptions.workspaceFolder
|
|
};
|
|
this._clientOptions.synchronize = this._clientOptions.synchronize || {};
|
|
this.state = ClientState.Initial;
|
|
this._connectionPromise = undefined;
|
|
this._resolvedConnection = undefined;
|
|
this._initializeResult = undefined;
|
|
if (clientOptions.outputChannel) {
|
|
this._outputChannel = clientOptions.outputChannel;
|
|
this._disposeOutputChannel = false;
|
|
}
|
|
else {
|
|
this._outputChannel = undefined;
|
|
this._disposeOutputChannel = true;
|
|
}
|
|
this._listeners = undefined;
|
|
this._providers = undefined;
|
|
this._diagnostics = undefined;
|
|
this._fileEvents = [];
|
|
this._fileEventDelayer = new async_1.Delayer(250);
|
|
this._onReady = new Promise((resolve, reject) => {
|
|
this._onReadyCallbacks = new OnReady(resolve, reject);
|
|
});
|
|
this._onStop = undefined;
|
|
this._stateChangeEmitter = new vscode_languageserver_protocol_1.Emitter();
|
|
this._tracer = {
|
|
log: (messageOrDataObject, data) => {
|
|
if (Is.string(messageOrDataObject)) {
|
|
this.logTrace(messageOrDataObject, data);
|
|
}
|
|
else {
|
|
this.logObjectTrace(messageOrDataObject);
|
|
}
|
|
}
|
|
};
|
|
this._syncedDocuments = new Map();
|
|
this.registerBuiltinFeatures();
|
|
}
|
|
get state() {
|
|
return this._state;
|
|
}
|
|
get id() {
|
|
return this._id;
|
|
}
|
|
get name() {
|
|
return this._name;
|
|
}
|
|
set state(value) {
|
|
let oldState = this.getPublicState();
|
|
this._state = value;
|
|
let newState = this.getPublicState();
|
|
if (newState !== oldState) {
|
|
this._stateChangeEmitter.fire({ oldState, newState });
|
|
}
|
|
}
|
|
getPublicState() {
|
|
if (this.state === ClientState.Running) {
|
|
return State.Running;
|
|
}
|
|
else if (this.state === ClientState.Starting) {
|
|
return State.Starting;
|
|
}
|
|
else {
|
|
return State.Stopped;
|
|
}
|
|
}
|
|
get initializeResult() {
|
|
return this._initializeResult;
|
|
}
|
|
sendRequest(type, ...params) {
|
|
if (!this.isConnectionActive()) {
|
|
throw new Error('Language client is not ready yet');
|
|
}
|
|
this.forceDocumentSync();
|
|
try {
|
|
return this._resolvedConnection.sendRequest(type, ...params);
|
|
}
|
|
catch (error) {
|
|
this.error(`Sending request ${Is.string(type) ? type : type.method} failed.`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
onRequest(type, handler) {
|
|
if (!this.isConnectionActive()) {
|
|
throw new Error('Language client is not ready yet');
|
|
}
|
|
try {
|
|
this._resolvedConnection.onRequest(type, handler);
|
|
}
|
|
catch (error) {
|
|
this.error(`Registering request handler ${Is.string(type) ? type : type.method} failed.`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
sendNotification(type, params) {
|
|
if (!this.isConnectionActive()) {
|
|
throw new Error('Language client is not ready yet');
|
|
}
|
|
this.forceDocumentSync();
|
|
try {
|
|
this._resolvedConnection.sendNotification(type, params);
|
|
}
|
|
catch (error) {
|
|
this.error(`Sending notification ${Is.string(type) ? type : type.method} failed.`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
onNotification(type, handler) {
|
|
if (!this.isConnectionActive()) {
|
|
throw new Error('Language client is not ready yet');
|
|
}
|
|
try {
|
|
this._resolvedConnection.onNotification(type, handler);
|
|
}
|
|
catch (error) {
|
|
this.error(`Registering notification handler ${Is.string(type) ? type : type.method} failed.`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
get clientOptions() {
|
|
return this._clientOptions;
|
|
}
|
|
get onDidChangeState() {
|
|
return this._stateChangeEmitter.event;
|
|
}
|
|
get outputChannel() {
|
|
if (!this._outputChannel) {
|
|
let { outputChannelName } = this._clientOptions;
|
|
this._outputChannel = workspace_1.default.createOutputChannel(outputChannelName ? outputChannelName : this._name);
|
|
}
|
|
return this._outputChannel;
|
|
}
|
|
get diagnostics() {
|
|
return this._diagnostics;
|
|
}
|
|
createDefaultErrorHandler() {
|
|
return new DefaultErrorHandler(this._id);
|
|
}
|
|
set trace(value) {
|
|
this._trace = value;
|
|
this.onReady().then(() => {
|
|
this.resolveConnection().then(connection => {
|
|
connection.trace(this._trace, this._tracer, {
|
|
sendNotification: false,
|
|
traceFormat: this._traceFormat
|
|
});
|
|
});
|
|
}, () => { });
|
|
}
|
|
logObjectTrace(data) {
|
|
if (data.isLSPMessage && data.type) {
|
|
this.outputChannel.append(`[LSP - ${(new Date().toLocaleTimeString())}] `);
|
|
}
|
|
else {
|
|
this.outputChannel.append(`[Trace - ${(new Date().toLocaleTimeString())}] `);
|
|
}
|
|
if (data) {
|
|
this.outputChannel.appendLine(`${JSON.stringify(data)}`);
|
|
}
|
|
}
|
|
data2String(data) {
|
|
if (data instanceof vscode_languageserver_protocol_1.ResponseError) {
|
|
const responseError = data;
|
|
return ` Message: ${responseError.message}\n Code: ${responseError.code} ${responseError.data ? '\n' + responseError.data.toString() : ''}`;
|
|
}
|
|
if (data instanceof Error) {
|
|
if (Is.string(data.stack)) {
|
|
return data.stack;
|
|
}
|
|
return data.message;
|
|
}
|
|
if (Is.string(data)) {
|
|
return data;
|
|
}
|
|
return data.toString();
|
|
}
|
|
_appendOutput(type, message, data) {
|
|
let level = RevealOutputChannelOn.Error;
|
|
switch (type) {
|
|
case 'Info':
|
|
level = RevealOutputChannelOn.Info;
|
|
break;
|
|
case 'Warn':
|
|
level = RevealOutputChannelOn.Warn;
|
|
break;
|
|
}
|
|
this.outputChannel.appendLine(`[${type} - ${(new Date().toLocaleTimeString())}] ${message}`);
|
|
let dataString;
|
|
if (data) {
|
|
dataString = this.data2String(data);
|
|
this.outputChannel.appendLine(dataString);
|
|
}
|
|
if (this._clientOptions.revealOutputChannelOn <= level) {
|
|
this.outputChannel.show(true);
|
|
}
|
|
}
|
|
info(message, data) {
|
|
this._appendOutput('Info', message, data);
|
|
}
|
|
warn(message, data) {
|
|
this._appendOutput('Warn', message, data);
|
|
}
|
|
error(message, data) {
|
|
this._appendOutput('Error', message, data);
|
|
}
|
|
logTrace(message, data) {
|
|
this.outputChannel.appendLine(`[Trace - ${(new Date().toLocaleTimeString())}] ${message}`);
|
|
if (data) {
|
|
this.outputChannel.appendLine(this.data2String(data));
|
|
}
|
|
}
|
|
needsStart() {
|
|
return (this.state === ClientState.Initial ||
|
|
this.state === ClientState.Stopping ||
|
|
this.state === ClientState.Stopped);
|
|
}
|
|
needsStop() {
|
|
return (this.state === ClientState.Starting || this.state === ClientState.Running);
|
|
}
|
|
onReady() {
|
|
return this._onReady;
|
|
}
|
|
get started() {
|
|
return this.state != ClientState.Initial;
|
|
}
|
|
isConnectionActive() {
|
|
return this.state === ClientState.Running && !!this._resolvedConnection;
|
|
}
|
|
start() {
|
|
if (this._onReadyCallbacks.isUsed) {
|
|
this._onReady = new Promise((resolve, reject) => {
|
|
this._onReadyCallbacks = new OnReady(resolve, reject);
|
|
});
|
|
}
|
|
this._listeners = [];
|
|
this._providers = [];
|
|
// If we restart then the diagnostics collection is reused.
|
|
if (!this._diagnostics) {
|
|
this._diagnostics = this._clientOptions.diagnosticCollectionName
|
|
? languages_1.default.createDiagnosticCollection(this._clientOptions.diagnosticCollectionName)
|
|
: languages_1.default.createDiagnosticCollection(this._id);
|
|
}
|
|
this.state = ClientState.Starting;
|
|
this.resolveConnection()
|
|
.then(connection => {
|
|
connection.onLogMessage(message => {
|
|
switch (message.type) {
|
|
case vscode_languageserver_protocol_1.MessageType.Error:
|
|
this.error(message.message);
|
|
break;
|
|
case vscode_languageserver_protocol_1.MessageType.Warning:
|
|
this.warn(message.message);
|
|
break;
|
|
case vscode_languageserver_protocol_1.MessageType.Info:
|
|
this.info(message.message);
|
|
break;
|
|
default:
|
|
this.outputChannel.appendLine(message.message);
|
|
}
|
|
});
|
|
connection.onShowMessage(message => {
|
|
switch (message.type) {
|
|
case vscode_languageserver_protocol_1.MessageType.Error:
|
|
workspace_1.default.showMessage(message.message, 'error');
|
|
break;
|
|
case vscode_languageserver_protocol_1.MessageType.Warning:
|
|
workspace_1.default.showMessage(message.message, 'warning');
|
|
break;
|
|
case vscode_languageserver_protocol_1.MessageType.Info:
|
|
workspace_1.default.showMessage(message.message);
|
|
break;
|
|
default:
|
|
workspace_1.default.showMessage(message.message);
|
|
}
|
|
});
|
|
connection.onRequest(vscode_languageserver_protocol_1.ShowMessageRequest.type, params => {
|
|
if (!params.actions || params.actions.length == 0) {
|
|
let msgType = params.type == vscode_languageserver_protocol_1.MessageType.Error
|
|
? 'error' : params.type == vscode_languageserver_protocol_1.MessageType.Warning ? 'warning' : 'more';
|
|
workspace_1.default.showMessage(params.message, msgType);
|
|
return Promise.resolve(null);
|
|
}
|
|
let items = params.actions.map(o => typeof o === 'string' ? o : o.title);
|
|
return workspace_1.default.showQuickpick(items, params.message).then(idx => {
|
|
return params.actions[idx];
|
|
});
|
|
});
|
|
connection.onTelemetry(_data => {
|
|
// ignored
|
|
});
|
|
connection.listen();
|
|
// Error is handled in the intialize call.
|
|
return this.initialize(connection);
|
|
}).then(undefined, error => {
|
|
this.state = ClientState.StartFailed;
|
|
this._onReadyCallbacks.reject(error);
|
|
this.error('Starting client failed: ', error);
|
|
});
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
if (this.needsStop()) {
|
|
this.stop();
|
|
}
|
|
});
|
|
}
|
|
resolveConnection() {
|
|
if (!this._connectionPromise) {
|
|
this._connectionPromise = this.createConnection();
|
|
}
|
|
return this._connectionPromise;
|
|
}
|
|
resolveRootPath() {
|
|
if (this._clientOptions.workspaceFolder) {
|
|
return vscode_uri_1.URI.parse(this._clientOptions.workspaceFolder.uri).fsPath;
|
|
}
|
|
let { ignoredRootPaths } = this._clientOptions;
|
|
let config = workspace_1.default.getConfiguration(this.id);
|
|
let rootPatterns = config.get('rootPatterns', []);
|
|
let required = config.get('requireRootPattern', false);
|
|
let resolved;
|
|
if (rootPatterns && rootPatterns.length) {
|
|
let doc = workspace_1.default.getDocument(workspace_1.default.bufnr);
|
|
if (doc && doc.schema == 'file') {
|
|
let dir = path_1.default.dirname(vscode_uri_1.URI.parse(doc.uri).fsPath);
|
|
resolved = fs_1.resolveRoot(dir, rootPatterns, workspace_1.default.cwd);
|
|
}
|
|
}
|
|
if (required && !resolved)
|
|
return null;
|
|
let rootPath = resolved || workspace_1.default.rootPath || workspace_1.default.cwd;
|
|
if (ignoredRootPaths && ignoredRootPaths.indexOf(rootPath) !== -1) {
|
|
workspace_1.default.showMessage(`Ignored rootPath ${rootPath} of client "${this._id}"`, 'warning');
|
|
return null;
|
|
}
|
|
return rootPath;
|
|
}
|
|
initialize(connection) {
|
|
this.refreshTrace(connection, false);
|
|
let initOption = this._clientOptions.initializationOptions;
|
|
let rootPath = this.resolveRootPath();
|
|
if (!rootPath)
|
|
return;
|
|
let initParams = {
|
|
processId: process.pid,
|
|
rootPath: rootPath ? rootPath : null,
|
|
rootUri: rootPath ? cv.asUri(vscode_uri_1.URI.file(rootPath)) : null,
|
|
capabilities: this.computeClientCapabilities(),
|
|
initializationOptions: Is.func(initOption) ? initOption() : initOption,
|
|
trace: vscode_languageserver_protocol_1.Trace.toString(this._trace),
|
|
};
|
|
this.fillInitializeParams(initParams);
|
|
return connection
|
|
.initialize(initParams)
|
|
.then(result => {
|
|
this._resolvedConnection = connection;
|
|
this._initializeResult = result;
|
|
this.state = ClientState.Running;
|
|
let textDocumentSyncOptions = undefined;
|
|
if (Is.number(result.capabilities.textDocumentSync)) {
|
|
if (result.capabilities.textDocumentSync === vscode_languageserver_protocol_1.TextDocumentSyncKind.None) {
|
|
textDocumentSyncOptions = {
|
|
openClose: false,
|
|
change: vscode_languageserver_protocol_1.TextDocumentSyncKind.None,
|
|
save: undefined
|
|
};
|
|
}
|
|
else {
|
|
textDocumentSyncOptions = {
|
|
openClose: true,
|
|
change: result.capabilities.textDocumentSync,
|
|
save: {
|
|
includeText: false
|
|
}
|
|
};
|
|
}
|
|
}
|
|
else if (result.capabilities.textDocumentSync != null) {
|
|
textDocumentSyncOptions = result.capabilities.textDocumentSync;
|
|
}
|
|
this._capabilities = Object.assign({}, result.capabilities, {
|
|
resolvedTextDocumentSync: textDocumentSyncOptions
|
|
});
|
|
if (!this._clientOptions.disableDiagnostics) {
|
|
connection.onDiagnostics(params => this.handleDiagnostics(params));
|
|
}
|
|
connection.onRequest(vscode_languageserver_protocol_1.RegistrationRequest.type, params => this.handleRegistrationRequest(params));
|
|
// See https://github.com/Microsoft/vscode-languageserver-node/issues/199
|
|
connection.onRequest('client/registerFeature', params => this.handleRegistrationRequest(params));
|
|
connection.onRequest(vscode_languageserver_protocol_1.UnregistrationRequest.type, params => this.handleUnregistrationRequest(params));
|
|
// See https://github.com/Microsoft/vscode-languageserver-node/issues/199
|
|
connection.onRequest('client/unregisterFeature', params => this.handleUnregistrationRequest(params));
|
|
connection.onRequest(vscode_languageserver_protocol_1.ApplyWorkspaceEditRequest.type, params => this.handleApplyWorkspaceEdit(params));
|
|
connection.sendNotification(vscode_languageserver_protocol_1.InitializedNotification.type, {});
|
|
this.hookFileEvents(connection);
|
|
this.hookConfigurationChanged(connection);
|
|
this.initializeFeatures(connection);
|
|
this._onReadyCallbacks.resolve();
|
|
return result;
|
|
}).then(undefined, error => {
|
|
if (this._clientOptions.initializationFailedHandler) {
|
|
if (this._clientOptions.initializationFailedHandler(error)) {
|
|
this.initialize(connection);
|
|
}
|
|
else {
|
|
this.stop();
|
|
this._onReadyCallbacks.reject(error);
|
|
}
|
|
}
|
|
else if (error instanceof vscode_languageserver_protocol_1.ResponseError &&
|
|
error.data &&
|
|
error.data.retry) {
|
|
workspace_1.default.showPrompt(error.message + ' Retry?').then(confirmed => {
|
|
if (confirmed) {
|
|
this.initialize(connection);
|
|
}
|
|
else {
|
|
this.stop();
|
|
this._onReadyCallbacks.reject(error);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
if (error && error.message) {
|
|
workspace_1.default.showMessage(error.message, 'error');
|
|
}
|
|
this.error('Server initialization failed.', error);
|
|
this.stop();
|
|
this._onReadyCallbacks.reject(error);
|
|
}
|
|
});
|
|
}
|
|
stop() {
|
|
this._initializeResult = undefined;
|
|
if (!this._connectionPromise) {
|
|
this.state = ClientState.Stopped;
|
|
return Promise.resolve();
|
|
}
|
|
if (this.state === ClientState.Stopping && this._onStop) {
|
|
return this._onStop;
|
|
}
|
|
this.state = ClientState.Stopping;
|
|
this.cleanUp();
|
|
// unkook listeners
|
|
return (this._onStop = this.resolveConnection().then(connection => {
|
|
return connection.shutdown().then(() => {
|
|
connection.exit();
|
|
connection.dispose();
|
|
this.state = ClientState.Stopped;
|
|
this._onStop = undefined;
|
|
this._connectionPromise = undefined;
|
|
this._resolvedConnection = undefined;
|
|
});
|
|
}));
|
|
}
|
|
cleanUp(channel = true, diagnostics = true) {
|
|
if (this._listeners) {
|
|
this._listeners.forEach(listener => listener.dispose());
|
|
this._listeners = undefined;
|
|
}
|
|
if (this._providers) {
|
|
this._providers.forEach(provider => provider.dispose());
|
|
this._providers = undefined;
|
|
}
|
|
if (this._syncedDocuments) {
|
|
this._syncedDocuments.clear();
|
|
}
|
|
for (let handler of this._dynamicFeatures.values()) {
|
|
handler.dispose();
|
|
}
|
|
if (channel && this._outputChannel && this._disposeOutputChannel) {
|
|
this._outputChannel.dispose();
|
|
this._outputChannel = undefined;
|
|
}
|
|
if (diagnostics && this._diagnostics) {
|
|
this._diagnostics.dispose();
|
|
this._diagnostics = undefined;
|
|
}
|
|
}
|
|
notifyFileEvent(event) {
|
|
this._fileEvents.push(event);
|
|
this._fileEventDelayer.trigger(() => {
|
|
this.onReady().then(() => {
|
|
this.resolveConnection().then(connection => {
|
|
if (this.isConnectionActive()) {
|
|
connection.didChangeWatchedFiles({ changes: this._fileEvents });
|
|
}
|
|
this._fileEvents = [];
|
|
});
|
|
}, error => {
|
|
this.error(`Notify file events failed.`, error);
|
|
});
|
|
});
|
|
}
|
|
forceDocumentSync() {
|
|
let doc = workspace_1.default.getDocument(workspace_1.default.bufnr);
|
|
if (doc)
|
|
doc.forceSync(false);
|
|
}
|
|
handleDiagnostics(params) {
|
|
if (!this._diagnostics) {
|
|
return;
|
|
}
|
|
let { uri, diagnostics } = params;
|
|
let middleware = this.clientOptions.middleware.handleDiagnostics;
|
|
if (middleware) {
|
|
middleware(uri, diagnostics, (uri, diagnostics) => this.setDiagnostics(uri, diagnostics));
|
|
}
|
|
else {
|
|
this.setDiagnostics(uri, diagnostics);
|
|
}
|
|
}
|
|
setDiagnostics(uri, diagnostics) {
|
|
if (!this._diagnostics) {
|
|
return;
|
|
}
|
|
this._diagnostics.set(uri, diagnostics);
|
|
}
|
|
createConnection() {
|
|
let errorHandler = (error, message, count) => {
|
|
logger.error('connection error:', error, message);
|
|
this.handleConnectionError(error, message, count);
|
|
};
|
|
let closeHandler = () => {
|
|
this.handleConnectionClosed();
|
|
};
|
|
return this.createMessageTransports(this._clientOptions.stdioEncoding || 'utf8').then(transports => {
|
|
return createConnection(transports.reader, transports.writer, errorHandler, closeHandler);
|
|
});
|
|
}
|
|
handleConnectionClosed() {
|
|
// Check whether this is a normal shutdown in progress or the client stopped normally.
|
|
if (this.state === ClientState.Stopping ||
|
|
this.state === ClientState.Stopped) {
|
|
return;
|
|
}
|
|
try {
|
|
if (this._resolvedConnection) {
|
|
this._resolvedConnection.dispose();
|
|
}
|
|
}
|
|
catch (error) {
|
|
// Disposing a connection could fail if error cases.
|
|
}
|
|
let action = CloseAction.DoNotRestart;
|
|
try {
|
|
action = this._clientOptions.errorHandler.closed();
|
|
}
|
|
catch (error) {
|
|
// Ignore errors coming from the error handler.
|
|
}
|
|
this._connectionPromise = undefined;
|
|
this._resolvedConnection = undefined;
|
|
if (action === CloseAction.DoNotRestart) {
|
|
this.error('Connection to server got closed. Server will not be restarted.');
|
|
this.state = ClientState.Stopped;
|
|
this.cleanUp(false, true);
|
|
}
|
|
else if (action === CloseAction.Restart) {
|
|
this.info('Connection to server got closed. Server will restart.');
|
|
this.cleanUp(false, false);
|
|
this.state = ClientState.Initial;
|
|
this.start();
|
|
}
|
|
}
|
|
restart() {
|
|
this.cleanUp(true, false);
|
|
this.start();
|
|
}
|
|
handleConnectionError(error, message, count) {
|
|
let action = this._clientOptions.errorHandler.error(error, message, count);
|
|
if (action === ErrorAction.Shutdown) {
|
|
this.error('Connection to server is erroring. Shutting down server.');
|
|
this.stop();
|
|
}
|
|
}
|
|
hookConfigurationChanged(connection) {
|
|
workspace_1.default.onDidChangeConfiguration(() => {
|
|
this.refreshTrace(connection, true);
|
|
});
|
|
}
|
|
refreshTrace(connection, sendNotification = false) {
|
|
let config = workspace_1.default.getConfiguration(this._id);
|
|
let trace = vscode_languageserver_protocol_1.Trace.Off;
|
|
let traceFormat = vscode_languageserver_protocol_1.TraceFormat.Text;
|
|
if (config) {
|
|
const traceConfig = config.get('trace.server', 'off');
|
|
if (typeof traceConfig === 'string') {
|
|
trace = vscode_languageserver_protocol_1.Trace.fromString(traceConfig);
|
|
}
|
|
else {
|
|
trace = vscode_languageserver_protocol_1.Trace.fromString(config.get('trace.server.verbosity', 'off'));
|
|
traceFormat = vscode_languageserver_protocol_1.TraceFormat.fromString(config.get('trace.server.format', 'text'));
|
|
}
|
|
}
|
|
this._trace = trace;
|
|
this._traceFormat = traceFormat;
|
|
connection.trace(this._trace, this._tracer, {
|
|
sendNotification,
|
|
traceFormat: this._traceFormat
|
|
});
|
|
}
|
|
hookFileEvents(_connection) {
|
|
let fileEvents = this._clientOptions.synchronize.fileEvents;
|
|
if (!fileEvents)
|
|
return;
|
|
let watchers;
|
|
if (Array.isArray(fileEvents)) {
|
|
watchers = fileEvents;
|
|
}
|
|
else {
|
|
watchers = [fileEvents];
|
|
}
|
|
if (!watchers) {
|
|
return;
|
|
}
|
|
this._dynamicFeatures.get(vscode_languageserver_protocol_1.DidChangeWatchedFilesNotification.type.method).registerRaw(UUID.generateUuid(), watchers);
|
|
}
|
|
registerFeatures(features) {
|
|
for (let feature of features) {
|
|
this.registerFeature(feature);
|
|
}
|
|
}
|
|
registerFeature(feature) {
|
|
this._features.push(feature);
|
|
if (DynamicFeature.is(feature)) {
|
|
let messages = feature.messages;
|
|
if (Array.isArray(messages)) {
|
|
for (let message of messages) {
|
|
this._method2Message.set(message.method, message);
|
|
this._dynamicFeatures.set(message.method, feature);
|
|
}
|
|
}
|
|
else {
|
|
this._method2Message.set(messages.method, messages);
|
|
this._dynamicFeatures.set(messages.method, feature);
|
|
}
|
|
}
|
|
}
|
|
registerBuiltinFeatures() {
|
|
this.registerFeature(new ConfigurationFeature(this));
|
|
this.registerFeature(new DidOpenTextDocumentFeature(this, this._syncedDocuments));
|
|
this.registerFeature(new DidChangeTextDocumentFeature(this));
|
|
this.registerFeature(new WillSaveFeature(this));
|
|
this.registerFeature(new WillSaveWaitUntilFeature(this));
|
|
this.registerFeature(new DidSaveTextDocumentFeature(this));
|
|
this.registerFeature(new DidCloseTextDocumentFeature(this, this._syncedDocuments));
|
|
this.registerFeature(new FileSystemWatcherFeature(this, event => this.notifyFileEvent(event)));
|
|
if (!this._clientOptions.disableCompletion) {
|
|
this.registerFeature(new CompletionItemFeature(this));
|
|
}
|
|
this.registerFeature(new HoverFeature(this));
|
|
this.registerFeature(new SignatureHelpFeature(this));
|
|
this.registerFeature(new DefinitionFeature(this));
|
|
this.registerFeature(new ReferencesFeature(this));
|
|
this.registerFeature(new DocumentHighlightFeature(this));
|
|
this.registerFeature(new DocumentSymbolFeature(this));
|
|
this.registerFeature(new WorkspaceSymbolFeature(this));
|
|
this.registerFeature(new CodeActionFeature(this));
|
|
this.registerFeature(new CodeLensFeature(this));
|
|
this.registerFeature(new DocumentFormattingFeature(this));
|
|
this.registerFeature(new DocumentRangeFormattingFeature(this));
|
|
this.registerFeature(new DocumentOnTypeFormattingFeature(this));
|
|
this.registerFeature(new RenameFeature(this));
|
|
this.registerFeature(new DocumentLinkFeature(this));
|
|
this.registerFeature(new ExecuteCommandFeature(this));
|
|
}
|
|
fillInitializeParams(params) {
|
|
for (let feature of this._features) {
|
|
if (Is.func(feature.fillInitializeParams)) {
|
|
feature.fillInitializeParams(params);
|
|
}
|
|
}
|
|
}
|
|
computeClientCapabilities() {
|
|
let result = {};
|
|
ensure(result, 'workspace').applyEdit = true;
|
|
let workspaceEdit = ensure(ensure(result, 'workspace'), 'workspaceEdit');
|
|
workspaceEdit.documentChanges = true;
|
|
workspaceEdit.resourceOperations = [vscode_languageserver_protocol_1.ResourceOperationKind.Create, vscode_languageserver_protocol_1.ResourceOperationKind.Rename, vscode_languageserver_protocol_1.ResourceOperationKind.Delete];
|
|
workspaceEdit.failureHandling = vscode_languageserver_protocol_1.FailureHandlingKind.TextOnlyTransactional;
|
|
ensure(ensure(result, 'textDocument'), 'publishDiagnostics').relatedInformation = true;
|
|
for (let feature of this._features) {
|
|
feature.fillClientCapabilities(result);
|
|
}
|
|
return result;
|
|
}
|
|
initializeFeatures(_connection) {
|
|
let documentSelector = this._clientOptions.documentSelector;
|
|
for (let feature of this._features) {
|
|
feature.initialize(this._capabilities, documentSelector);
|
|
}
|
|
}
|
|
handleRegistrationRequest(params) {
|
|
if (this.clientOptions.disableDynamicRegister)
|
|
return Promise.resolve();
|
|
return new Promise((resolve, reject) => {
|
|
for (let registration of params.registrations) {
|
|
const feature = this._dynamicFeatures.get(registration.method);
|
|
if (!feature) {
|
|
reject(new Error(`No feature implementation for ${registration.method} found. Registration failed.`));
|
|
return;
|
|
}
|
|
const options = registration.registerOptions || {};
|
|
options.documentSelector =
|
|
options.documentSelector || this._clientOptions.documentSelector;
|
|
const data = {
|
|
id: registration.id,
|
|
registerOptions: options
|
|
};
|
|
feature.register(this._method2Message.get(registration.method), data);
|
|
}
|
|
resolve();
|
|
});
|
|
}
|
|
handleUnregistrationRequest(params) {
|
|
return new Promise((resolve, reject) => {
|
|
for (let unregistration of params.unregisterations) {
|
|
const feature = this._dynamicFeatures.get(unregistration.method);
|
|
if (!feature) {
|
|
reject(new Error(`No feature implementation for ${unregistration.method} found. Unregistration failed.`));
|
|
return;
|
|
}
|
|
feature.unregister(unregistration.id);
|
|
}
|
|
resolve();
|
|
});
|
|
}
|
|
handleApplyWorkspaceEdit(params) {
|
|
return workspace_1.default.applyEdit(params.edit).then(value => {
|
|
return { applied: value };
|
|
});
|
|
}
|
|
logFailedRequest(type, error) {
|
|
// If we get a request cancel don't log anything.
|
|
if (error instanceof vscode_languageserver_protocol_1.ResponseError &&
|
|
error.code === vscode_languageserver_protocol_1.ErrorCodes.RequestCancelled) {
|
|
return;
|
|
}
|
|
this.error(`Request ${type.method} failed.`, error);
|
|
}
|
|
}
|
|
exports.BaseLanguageClient = BaseLanguageClient;
|
|
//# sourceMappingURL=client.js.map
|
|
|
|
/***/ }),
|
|
/* 354 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
/**
|
|
* A helper to delay execution of a task that is being requested often.
|
|
*
|
|
* Following the throttler, now imagine the mail man wants to optimize the number of
|
|
* trips proactively. The trip itself can be long, so he decides not to make the trip
|
|
* as soon as a letter is submitted. Instead he waits a while, in case more
|
|
* letters are submitted. After said waiting period, if no letters were submitted, he
|
|
* decides to make the trip. Imagine that N more letters were submitted after the first
|
|
* one, all within a short period of time between each other. Even though N+1
|
|
* submissions occurred, only 1 delivery was made.
|
|
*
|
|
* The delayer offers this behavior via the trigger() method, into which both the task
|
|
* to be executed and the waiting period (delay) must be passed in as arguments. Following
|
|
* the example:
|
|
*
|
|
* const delayer = new Delayer(WAITING_PERIOD)
|
|
* const letters = []
|
|
*
|
|
* function letterReceived(l) {
|
|
* letters.push(l)
|
|
* delayer.trigger(() => { return makeTheTrip(); })
|
|
* }
|
|
*/
|
|
class Delayer {
|
|
constructor(defaultDelay) {
|
|
this.defaultDelay = defaultDelay;
|
|
this.timeout = null;
|
|
this.completionPromise = null;
|
|
this.doResolve = null;
|
|
this.task = null;
|
|
}
|
|
trigger(task, delay = this.defaultDelay) {
|
|
this.task = task;
|
|
this.cancelTimeout();
|
|
if (!this.completionPromise) {
|
|
this.completionPromise = new Promise((c, e) => {
|
|
this.doResolve = c;
|
|
this.doReject = e;
|
|
}).then(() => {
|
|
this.completionPromise = null;
|
|
this.doResolve = null;
|
|
const task = this.task;
|
|
this.task = null;
|
|
return task();
|
|
});
|
|
}
|
|
this.timeout = setTimeout(() => {
|
|
this.timeout = null;
|
|
this.doResolve(null);
|
|
}, delay);
|
|
return this.completionPromise;
|
|
}
|
|
isTriggered() {
|
|
return this.timeout !== null;
|
|
}
|
|
cancel() {
|
|
this.cancelTimeout();
|
|
if (this.completionPromise) {
|
|
this.doReject(new Error('Canceled'));
|
|
this.completionPromise = null;
|
|
}
|
|
}
|
|
cancelTimeout() {
|
|
if (this.timeout !== null) {
|
|
clearTimeout(this.timeout);
|
|
this.timeout = null;
|
|
}
|
|
}
|
|
dispose() {
|
|
this.cancelTimeout();
|
|
}
|
|
}
|
|
exports.Delayer = Delayer;
|
|
//# sourceMappingURL=async.js.map
|
|
|
|
/***/ }),
|
|
/* 355 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const lodash_1 = __webpack_require__(312);
|
|
function asLanguageIds(documentSelector) {
|
|
let res = documentSelector.map(filter => {
|
|
if (typeof filter == 'string') {
|
|
return filter;
|
|
}
|
|
return filter.language;
|
|
});
|
|
res = res.filter(s => s != null);
|
|
return res.length == 0 ? null : res;
|
|
}
|
|
exports.asLanguageIds = asLanguageIds;
|
|
function convertToTextDocumentItem(document) {
|
|
return {
|
|
uri: document.uri,
|
|
languageId: document.languageId,
|
|
version: document.version,
|
|
text: document.getText()
|
|
};
|
|
}
|
|
exports.convertToTextDocumentItem = convertToTextDocumentItem;
|
|
function asCloseTextDocumentParams(document) {
|
|
return {
|
|
textDocument: {
|
|
uri: document.uri
|
|
}
|
|
};
|
|
}
|
|
exports.asCloseTextDocumentParams = asCloseTextDocumentParams;
|
|
function asChangeTextDocumentParams(document) {
|
|
let result = {
|
|
textDocument: {
|
|
uri: document.uri,
|
|
version: document.version
|
|
},
|
|
contentChanges: [{ text: document.getText() }]
|
|
};
|
|
return result;
|
|
}
|
|
exports.asChangeTextDocumentParams = asChangeTextDocumentParams;
|
|
function asWillSaveTextDocumentParams(event) {
|
|
return {
|
|
textDocument: asVersionedTextDocumentIdentifier(event.document),
|
|
reason: event.reason
|
|
};
|
|
}
|
|
exports.asWillSaveTextDocumentParams = asWillSaveTextDocumentParams;
|
|
function asVersionedTextDocumentIdentifier(textDocument) {
|
|
return {
|
|
uri: textDocument.uri,
|
|
version: textDocument.version
|
|
};
|
|
}
|
|
exports.asVersionedTextDocumentIdentifier = asVersionedTextDocumentIdentifier;
|
|
function asSaveTextDocumentParams(document, includeText) {
|
|
let result = {
|
|
textDocument: asVersionedTextDocumentIdentifier(document)
|
|
};
|
|
if (includeText) {
|
|
result.text = document.getText();
|
|
}
|
|
return result;
|
|
}
|
|
exports.asSaveTextDocumentParams = asSaveTextDocumentParams;
|
|
function asUri(resource) {
|
|
return resource.toString();
|
|
}
|
|
exports.asUri = asUri;
|
|
function asCompletionParams(textDocument, position, context) {
|
|
return {
|
|
textDocument: {
|
|
uri: textDocument.uri,
|
|
},
|
|
position,
|
|
context: lodash_1.omit(context, ['option']),
|
|
};
|
|
}
|
|
exports.asCompletionParams = asCompletionParams;
|
|
function asTextDocumentPositionParams(textDocument, position) {
|
|
return {
|
|
textDocument: {
|
|
uri: textDocument.uri,
|
|
},
|
|
position
|
|
};
|
|
}
|
|
exports.asTextDocumentPositionParams = asTextDocumentPositionParams;
|
|
function asTextDocumentIdentifier(textDocument) {
|
|
return {
|
|
uri: textDocument.uri
|
|
};
|
|
}
|
|
exports.asTextDocumentIdentifier = asTextDocumentIdentifier;
|
|
function asReferenceParams(textDocument, position, options) {
|
|
return {
|
|
textDocument: {
|
|
uri: textDocument.uri,
|
|
},
|
|
position,
|
|
context: { includeDeclaration: options.includeDeclaration }
|
|
};
|
|
}
|
|
exports.asReferenceParams = asReferenceParams;
|
|
function asDocumentSymbolParams(textDocument) {
|
|
return {
|
|
textDocument: {
|
|
uri: textDocument.uri
|
|
}
|
|
};
|
|
}
|
|
exports.asDocumentSymbolParams = asDocumentSymbolParams;
|
|
function asCodeLensParams(textDocument) {
|
|
return {
|
|
textDocument: {
|
|
uri: textDocument.uri
|
|
}
|
|
};
|
|
}
|
|
exports.asCodeLensParams = asCodeLensParams;
|
|
//# sourceMappingURL=converter.js.map
|
|
|
|
/***/ }),
|
|
/* 356 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const uuidv4 = __webpack_require__(321);
|
|
function generateUuid() {
|
|
return uuidv4();
|
|
}
|
|
exports.generateUuid = generateUuid;
|
|
//# sourceMappingURL=uuid.js.map
|
|
|
|
/***/ }),
|
|
/* 357 */
|
|
/***/ (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 tslib_1 = __webpack_require__(3);
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const languages_1 = tslib_1.__importDefault(__webpack_require__(315));
|
|
const Is = tslib_1.__importStar(__webpack_require__(191));
|
|
const client_1 = __webpack_require__(353);
|
|
const UUID = tslib_1.__importStar(__webpack_require__(356));
|
|
function ensure(target, key) {
|
|
if (target[key] === void 0) {
|
|
target[key] = {};
|
|
}
|
|
return target[key];
|
|
}
|
|
class ColorProviderFeature extends client_1.TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DocumentColorRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
ensure(ensure(capabilites, 'textDocument'), 'colorProvider').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.colorProvider) {
|
|
return;
|
|
}
|
|
const implCapabilities = capabilities.colorProvider;
|
|
const id = Is.string(implCapabilities.id) && implCapabilities.id.length > 0
|
|
? implCapabilities.id
|
|
: UUID.generateUuid();
|
|
const selector = implCapabilities.documentSelector || documentSelector;
|
|
if (selector) {
|
|
this.register(this.messages, {
|
|
id,
|
|
registerOptions: Object.assign({}, { documentSelector: selector })
|
|
});
|
|
}
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideColorPresentations = (color, context, token) => {
|
|
const requestParams = {
|
|
color,
|
|
textDocument: {
|
|
uri: context.document.uri
|
|
},
|
|
range: context.range
|
|
};
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.ColorPresentationRequest.type, requestParams, token)
|
|
.then(res => res, (error) => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.ColorPresentationRequest.type, error);
|
|
return Promise.resolve(null);
|
|
});
|
|
};
|
|
let provideDocumentColors = (document, token) => {
|
|
const requestParams = {
|
|
textDocument: {
|
|
uri: document.uri
|
|
}
|
|
};
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.DocumentColorRequest.type, requestParams, token)
|
|
.then(res => res, (error) => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.ColorPresentationRequest.type, error);
|
|
return Promise.resolve(null);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerDocumentColorProvider(options.documentSelector, {
|
|
provideColorPresentations: (color, context, token) => {
|
|
return middleware.provideColorPresentations
|
|
? middleware.provideColorPresentations(color, context, token, provideColorPresentations)
|
|
: provideColorPresentations(color, context, token);
|
|
},
|
|
provideDocumentColors: (document, token) => {
|
|
return middleware.provideDocumentColors
|
|
? middleware.provideDocumentColors(document, token, provideDocumentColors)
|
|
: provideDocumentColors(document, token);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
exports.ColorProviderFeature = ColorProviderFeature;
|
|
//# sourceMappingURL=colorProvider.js.map
|
|
|
|
/***/ }),
|
|
/* 358 */
|
|
/***/ (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 vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('languageclient-configuration');
|
|
class ConfigurationFeature {
|
|
constructor(_client) {
|
|
this._client = _client;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
capabilities.workspace = capabilities.workspace || {};
|
|
capabilities.workspace.configuration = true;
|
|
}
|
|
initialize() {
|
|
let client = this._client;
|
|
client.onRequest(vscode_languageserver_protocol_1.ConfigurationRequest.type, (params, token) => {
|
|
let configuration = params => {
|
|
let result = [];
|
|
for (let item of params.items) {
|
|
result.push(this.getConfiguration(item.scopeUri, item.section));
|
|
}
|
|
return result;
|
|
};
|
|
let middleware = client.clientOptions.middleware.workspace;
|
|
return middleware && middleware.configuration
|
|
? middleware.configuration(params, token, configuration)
|
|
: configuration(params, token);
|
|
});
|
|
}
|
|
getConfiguration(resource, section) {
|
|
let result = null;
|
|
let { id } = this._client;
|
|
if (section) {
|
|
if (id.startsWith('languageserver')) {
|
|
let config = workspace_1.default.getConfiguration(id, resource).get('settings');
|
|
if (config && config[section] != null)
|
|
return config[section];
|
|
}
|
|
let index = section.lastIndexOf('.');
|
|
if (index === -1) {
|
|
result = workspace_1.default.getConfiguration(undefined, resource).get(section, {});
|
|
}
|
|
else {
|
|
let config = workspace_1.default.getConfiguration(section.substr(0, index), resource);
|
|
if (config) {
|
|
result = config.get(section.substr(index + 1));
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
let config = workspace_1.default.getConfiguration(undefined, resource);
|
|
result = {};
|
|
for (let key of Object.keys(config)) {
|
|
if (config.has(key)) {
|
|
result[key] = config.get(key);
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
exports.ConfigurationFeature = ConfigurationFeature;
|
|
//# sourceMappingURL=configuration.js.map
|
|
|
|
/***/ }),
|
|
/* 359 */
|
|
/***/ (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 tslib_1 = __webpack_require__(3);
|
|
const Is = tslib_1.__importStar(__webpack_require__(191));
|
|
const UUID = tslib_1.__importStar(__webpack_require__(356));
|
|
const languages_1 = tslib_1.__importDefault(__webpack_require__(315));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const converter_1 = __webpack_require__(355);
|
|
const client_1 = __webpack_require__(353);
|
|
function ensure(target, key) {
|
|
if (target[key] === void 0) {
|
|
target[key] = {};
|
|
}
|
|
return target[key];
|
|
}
|
|
class DeclarationFeature extends client_1.TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DeclarationRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
let declarationSupport = ensure(ensure(capabilites, 'textDocument'), 'declaration');
|
|
declarationSupport.dynamicRegistration = true;
|
|
// declarationSupport.linkSupport = true
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.declarationProvider) {
|
|
return;
|
|
}
|
|
if (capabilities.declarationProvider === true) {
|
|
if (!documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector })
|
|
});
|
|
}
|
|
else {
|
|
const declCapabilities = capabilities.declarationProvider;
|
|
const id = Is.string(declCapabilities.id) && declCapabilities.id.length > 0 ? declCapabilities.id : UUID.generateUuid();
|
|
const selector = declCapabilities.documentSelector || documentSelector;
|
|
if (selector) {
|
|
this.register(this.messages, {
|
|
id,
|
|
registerOptions: Object.assign({}, { documentSelector: selector })
|
|
});
|
|
}
|
|
}
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideDeclaration = (document, position, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.DeclarationRequest.type, converter_1.asTextDocumentPositionParams(document, position), token).then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.DeclarationRequest.type, error);
|
|
return Promise.resolve(null);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerDeclarationProvider(options.documentSelector, {
|
|
provideDeclaration: (document, position, token) => {
|
|
return middleware.provideDeclaration
|
|
? middleware.provideDeclaration(document, position, token, provideDeclaration)
|
|
: provideDeclaration(document, position, token);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
exports.DeclarationFeature = DeclarationFeature;
|
|
//# sourceMappingURL=declaration.js.map
|
|
|
|
/***/ }),
|
|
/* 360 */
|
|
/***/ (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 tslib_1 = __webpack_require__(3);
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const languages_1 = tslib_1.__importDefault(__webpack_require__(315));
|
|
const Is = tslib_1.__importStar(__webpack_require__(191));
|
|
const client_1 = __webpack_require__(353);
|
|
const UUID = tslib_1.__importStar(__webpack_require__(356));
|
|
function ensure(target, key) {
|
|
if (target[key] === void 0) {
|
|
target[key] = {};
|
|
}
|
|
return target[key];
|
|
}
|
|
class FoldingRangeFeature extends client_1.TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.FoldingRangeRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
let capability = ensure(ensure(capabilites, 'textDocument'), 'foldingRange');
|
|
capability.dynamicRegistration = true;
|
|
capability.rangeLimit = 5000;
|
|
capability.lineFoldingOnly = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.foldingRangeProvider) {
|
|
return;
|
|
}
|
|
const implCapabilities = capabilities.foldingRangeProvider;
|
|
const id = Is.string(implCapabilities.id) && implCapabilities.id.length > 0
|
|
? implCapabilities.id
|
|
: UUID.generateUuid();
|
|
const selector = implCapabilities.documentSelector || documentSelector;
|
|
if (selector) {
|
|
this.register(this.messages, {
|
|
id,
|
|
registerOptions: Object.assign({}, { documentSelector: selector })
|
|
});
|
|
}
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideFoldingRanges = (document, _, token) => {
|
|
const requestParams = {
|
|
textDocument: {
|
|
uri: document.uri
|
|
}
|
|
};
|
|
return client
|
|
.sendRequest(vscode_languageserver_protocol_1.FoldingRangeRequest.type, requestParams, token)
|
|
.then(res => res, (error) => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.FoldingRangeRequest.type, error);
|
|
return Promise.resolve(null);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerFoldingRangeProvider(options.documentSelector, {
|
|
provideFoldingRanges(document, context, token) {
|
|
return middleware.provideFoldingRanges
|
|
? middleware.provideFoldingRanges(document, context, token, provideFoldingRanges)
|
|
: provideFoldingRanges(document, context, token);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
exports.FoldingRangeFeature = FoldingRangeFeature;
|
|
//# sourceMappingURL=foldingRange.js.map
|
|
|
|
/***/ }),
|
|
/* 361 */
|
|
/***/ (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 vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const languages_1 = tslib_1.__importDefault(__webpack_require__(315));
|
|
const Is = tslib_1.__importStar(__webpack_require__(191));
|
|
const client_1 = __webpack_require__(353);
|
|
const UUID = tslib_1.__importStar(__webpack_require__(356));
|
|
const cv = tslib_1.__importStar(__webpack_require__(355));
|
|
function ensure(target, key) {
|
|
if (target[key] === void 0) {
|
|
target[key] = {};
|
|
}
|
|
return target[key];
|
|
}
|
|
class ImplementationFeature extends client_1.TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.ImplementationRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
ensure(ensure(capabilites, 'textDocument'), 'implementation').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.implementationProvider) {
|
|
return;
|
|
}
|
|
if (capabilities.implementationProvider === true) {
|
|
if (!documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector })
|
|
});
|
|
}
|
|
else {
|
|
const implCapabilities = capabilities.implementationProvider;
|
|
const id = Is.string(implCapabilities.id) && implCapabilities.id.length > 0 ? implCapabilities.id : UUID.generateUuid();
|
|
const selector = implCapabilities.documentSelector || documentSelector;
|
|
if (selector) {
|
|
this.register(this.messages, {
|
|
id,
|
|
registerOptions: Object.assign({}, { documentSelector: selector })
|
|
});
|
|
}
|
|
}
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideImplementation = (document, position, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.ImplementationRequest.type, cv.asTextDocumentPositionParams(document, position), token)
|
|
.then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.ImplementationRequest.type, error);
|
|
return Promise.resolve(null);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerImplementationProvider(options.documentSelector, {
|
|
provideImplementation: (document, position, token) => {
|
|
return middleware.provideImplementation
|
|
? middleware.provideImplementation(document, position, token, provideImplementation)
|
|
: provideImplementation(document, position, token);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
exports.ImplementationFeature = ImplementationFeature;
|
|
//# sourceMappingURL=implementation.js.map
|
|
|
|
/***/ }),
|
|
/* 362 */
|
|
/***/ (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 vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const languages_1 = tslib_1.__importDefault(__webpack_require__(315));
|
|
const Is = tslib_1.__importStar(__webpack_require__(191));
|
|
const client_1 = __webpack_require__(353);
|
|
const UUID = tslib_1.__importStar(__webpack_require__(356));
|
|
const cv = tslib_1.__importStar(__webpack_require__(355));
|
|
function ensure(target, key) {
|
|
if (target[key] === void 0) {
|
|
target[key] = {};
|
|
}
|
|
return target[key];
|
|
}
|
|
class TypeDefinitionFeature extends client_1.TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.TypeDefinitionRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilites) {
|
|
ensure(ensure(capabilites, 'textDocument'), 'typeDefinition').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
if (!capabilities.typeDefinitionProvider) {
|
|
return;
|
|
}
|
|
if (capabilities.typeDefinitionProvider === true) {
|
|
if (!documentSelector) {
|
|
return;
|
|
}
|
|
this.register(this.messages, {
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector })
|
|
});
|
|
}
|
|
else {
|
|
const implCapabilities = capabilities.typeDefinitionProvider;
|
|
const id = Is.string(implCapabilities.id) && implCapabilities.id.length > 0
|
|
? implCapabilities.id
|
|
: UUID.generateUuid();
|
|
const selector = implCapabilities.documentSelector || documentSelector;
|
|
if (selector) {
|
|
this.register(this.messages, {
|
|
id,
|
|
registerOptions: Object.assign({}, { documentSelector: selector })
|
|
});
|
|
}
|
|
}
|
|
}
|
|
registerLanguageProvider(options) {
|
|
let client = this._client;
|
|
let provideTypeDefinition = (document, position, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.TypeDefinitionRequest.type, cv.asTextDocumentPositionParams(document, position), token)
|
|
.then(res => res, error => {
|
|
client.logFailedRequest(vscode_languageserver_protocol_1.TypeDefinitionRequest.type, error);
|
|
return Promise.resolve(null);
|
|
});
|
|
};
|
|
let middleware = client.clientOptions.middleware;
|
|
return languages_1.default.registerTypeDefinitionProvider(options.documentSelector, {
|
|
provideTypeDefinition: (document, position, token) => {
|
|
return middleware.provideTypeDefinition
|
|
? middleware.provideTypeDefinition(document, position, token, provideTypeDefinition)
|
|
: provideTypeDefinition(document, position, token);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
exports.TypeDefinitionFeature = TypeDefinitionFeature;
|
|
//# sourceMappingURL=typeDefinition.js.map
|
|
|
|
/***/ }),
|
|
/* 363 */
|
|
/***/ (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 tslib_1 = __webpack_require__(3);
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const UUID = tslib_1.__importStar(__webpack_require__(356));
|
|
const logger = __webpack_require__(186)('language-client-workspaceFolder');
|
|
function access(target, key) {
|
|
if (target === void 0) {
|
|
return undefined;
|
|
}
|
|
return target[key];
|
|
}
|
|
class WorkspaceFoldersFeature {
|
|
constructor(_client) {
|
|
this._client = _client;
|
|
this._listeners = new Map();
|
|
}
|
|
get messages() {
|
|
return vscode_languageserver_protocol_1.DidChangeWorkspaceFoldersNotification.type;
|
|
}
|
|
fillInitializeParams(params) {
|
|
params.workspaceFolders = workspace_1.default.workspaceFolders;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
capabilities.workspace = capabilities.workspace || {};
|
|
capabilities.workspace.workspaceFolders = true;
|
|
}
|
|
initialize(capabilities) {
|
|
let client = this._client;
|
|
client.onRequest(vscode_languageserver_protocol_1.WorkspaceFoldersRequest.type, (token) => {
|
|
let workspaceFolders = () => {
|
|
let { workspaceFolders } = workspace_1.default;
|
|
return workspaceFolders.length ? workspaceFolders : null;
|
|
};
|
|
let middleware = client.clientOptions.middleware.workspace;
|
|
return middleware && middleware.workspaceFolders
|
|
? middleware.workspaceFolders(token, workspaceFolders)
|
|
: workspaceFolders(token);
|
|
});
|
|
let value = access(access(access(capabilities, 'workspace'), 'workspaceFolders'), 'changeNotifications');
|
|
let id;
|
|
if (typeof value === 'string') {
|
|
id = value;
|
|
}
|
|
else if (value === true) {
|
|
id = UUID.generateUuid();
|
|
}
|
|
if (id) {
|
|
this.register(this.messages, {
|
|
id,
|
|
registerOptions: undefined
|
|
});
|
|
}
|
|
}
|
|
register(_message, data) {
|
|
let id = data.id;
|
|
let client = this._client;
|
|
let disposable = workspace_1.default.onDidChangeWorkspaceFolders(event => {
|
|
let didChangeWorkspaceFolders = (event) => {
|
|
let params = { event };
|
|
this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeWorkspaceFoldersNotification.type, params);
|
|
};
|
|
let middleware = client.clientOptions.middleware.workspace;
|
|
middleware && middleware.didChangeWorkspaceFolders
|
|
? middleware.didChangeWorkspaceFolders(event, didChangeWorkspaceFolders)
|
|
: didChangeWorkspaceFolders(event);
|
|
});
|
|
this._listeners.set(id, disposable);
|
|
}
|
|
unregister(id) {
|
|
let disposable = this._listeners.get(id);
|
|
if (disposable === void 0) {
|
|
return;
|
|
}
|
|
this._listeners.delete(id);
|
|
disposable.dispose();
|
|
}
|
|
dispose() {
|
|
for (let disposable of this._listeners.values()) {
|
|
disposable.dispose();
|
|
}
|
|
this._listeners.clear();
|
|
}
|
|
}
|
|
exports.WorkspaceFoldersFeature = WorkspaceFoldersFeature;
|
|
//# sourceMappingURL=workspaceFolders.js.map
|
|
|
|
/***/ }),
|
|
/* 364 */
|
|
/***/ (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__(176));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const extensions_1 = tslib_1.__importDefault(__webpack_require__(238));
|
|
const util_1 = __webpack_require__(174);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const highligher_1 = tslib_1.__importDefault(__webpack_require__(349));
|
|
const configuration_1 = tslib_1.__importDefault(__webpack_require__(365));
|
|
const history_1 = tslib_1.__importDefault(__webpack_require__(366));
|
|
const mappings_1 = tslib_1.__importDefault(__webpack_require__(368));
|
|
const prompt_1 = tslib_1.__importDefault(__webpack_require__(369));
|
|
const commands_1 = tslib_1.__importDefault(__webpack_require__(370));
|
|
const diagnostics_1 = tslib_1.__importDefault(__webpack_require__(372));
|
|
const extensions_2 = tslib_1.__importDefault(__webpack_require__(374));
|
|
const folders_1 = tslib_1.__importDefault(__webpack_require__(375));
|
|
const links_1 = tslib_1.__importDefault(__webpack_require__(376));
|
|
const lists_1 = tslib_1.__importDefault(__webpack_require__(377));
|
|
const location_1 = tslib_1.__importDefault(__webpack_require__(373));
|
|
const outline_1 = tslib_1.__importDefault(__webpack_require__(378));
|
|
const output_1 = tslib_1.__importDefault(__webpack_require__(380));
|
|
const services_1 = tslib_1.__importDefault(__webpack_require__(381));
|
|
const sources_1 = tslib_1.__importDefault(__webpack_require__(382));
|
|
const symbols_1 = tslib_1.__importDefault(__webpack_require__(383));
|
|
const actions_1 = tslib_1.__importDefault(__webpack_require__(385));
|
|
const ui_1 = tslib_1.__importDefault(__webpack_require__(386));
|
|
const worker_1 = tslib_1.__importDefault(__webpack_require__(387));
|
|
const logger = __webpack_require__(186)('list-manager');
|
|
const mouseKeys = ['<LeftMouse>', '<LeftDrag>', '<LeftRelease>', '<2-LeftMouse>'];
|
|
class ListManager {
|
|
constructor() {
|
|
this.plugTs = 0;
|
|
this.disposables = [];
|
|
this.args = [];
|
|
this.listArgs = [];
|
|
this.listMap = new Map();
|
|
this.activated = false;
|
|
this.executing = false;
|
|
}
|
|
init(nvim) {
|
|
this.nvim = nvim;
|
|
this.config = new configuration_1.default();
|
|
this.prompt = new prompt_1.default(nvim, this.config);
|
|
this.history = new history_1.default(this);
|
|
this.mappings = new mappings_1.default(this, nvim, this.config);
|
|
this.worker = new worker_1.default(nvim, this);
|
|
this.ui = new ui_1.default(nvim, this.config);
|
|
events_1.default.on('VimResized', () => {
|
|
if (this.isActivated)
|
|
nvim.command('redraw!', true);
|
|
}, null, this.disposables);
|
|
events_1.default.on('InputChar', this.onInputChar, this, this.disposables);
|
|
events_1.default.on('FocusGained', debounce_1.default(async () => {
|
|
if (this.activated)
|
|
this.prompt.drawPrompt();
|
|
}, 100), null, this.disposables);
|
|
events_1.default.on('BufEnter', debounce_1.default(async () => {
|
|
let { bufnr } = this.ui;
|
|
if (!bufnr)
|
|
return;
|
|
if (!this.activated) {
|
|
this.ui.hide();
|
|
return;
|
|
}
|
|
let curr = await nvim.call('bufnr', '%');
|
|
if (curr == bufnr) {
|
|
this.prompt.start();
|
|
}
|
|
else {
|
|
nvim.pauseNotification();
|
|
this.prompt.cancel();
|
|
await nvim.resumeNotification();
|
|
}
|
|
}, 100), null, this.disposables);
|
|
this.ui.onDidChangeLine(debounce_1.default(async () => {
|
|
if (!this.activated)
|
|
return;
|
|
let previewing = await nvim.call('coc#util#has_preview');
|
|
let mode = await this.nvim.mode;
|
|
if (mode.blocking || mode.mode != 'n')
|
|
return;
|
|
if (previewing)
|
|
await this.doAction('preview');
|
|
}, 100), null, this.disposables);
|
|
this.ui.onDidLineChange(debounce_1.default(async () => {
|
|
let { autoPreview } = this.listOptions;
|
|
if (!autoPreview || !this.activated)
|
|
return;
|
|
await this.doAction('preview');
|
|
}, 100), null, this.disposables);
|
|
this.ui.onDidChangeLine(this.resolveItem, this, this.disposables);
|
|
this.ui.onDidLineChange(this.resolveItem, this, this.disposables);
|
|
this.ui.onDidOpen(() => {
|
|
if (this.currList) {
|
|
if (typeof this.currList.doHighlight == 'function') {
|
|
this.currList.doHighlight();
|
|
}
|
|
}
|
|
}, null, this.disposables);
|
|
this.ui.onDidClose(async () => {
|
|
await this.cancel();
|
|
}, null, this.disposables);
|
|
this.ui.onDidChange(async () => {
|
|
if (this.activated) {
|
|
this.updateStatus();
|
|
}
|
|
this.prompt.drawPrompt();
|
|
}, null, this.disposables);
|
|
this.ui.onDidDoubleClick(async () => {
|
|
await this.doAction();
|
|
}, null, this.disposables);
|
|
this.worker.onDidChangeItems(async ({ items, highlights, reload, append }) => {
|
|
if (!this.activated)
|
|
return;
|
|
if (append) {
|
|
this.ui.addHighlights(highlights, true);
|
|
await this.ui.appendItems(items);
|
|
}
|
|
else {
|
|
this.ui.addHighlights(highlights);
|
|
await this.ui.drawItems(items, this.name, this.listOptions, reload);
|
|
}
|
|
}, null, this.disposables);
|
|
this.registerList(new links_1.default(nvim));
|
|
this.registerList(new location_1.default(nvim));
|
|
this.registerList(new symbols_1.default(nvim));
|
|
this.registerList(new outline_1.default(nvim));
|
|
this.registerList(new commands_1.default(nvim));
|
|
this.registerList(new extensions_2.default(nvim));
|
|
this.registerList(new diagnostics_1.default(nvim));
|
|
this.registerList(new sources_1.default(nvim));
|
|
this.registerList(new services_1.default(nvim));
|
|
this.registerList(new output_1.default(nvim));
|
|
this.registerList(new lists_1.default(nvim, this.listMap));
|
|
this.registerList(new folders_1.default(nvim));
|
|
this.registerList(new actions_1.default(nvim));
|
|
}
|
|
async start(args) {
|
|
if (this.activated)
|
|
return;
|
|
let res = this.parseArgs(args);
|
|
if (!res)
|
|
return;
|
|
this.args = args;
|
|
this.activated = true;
|
|
let { list, options, listArgs } = res;
|
|
try {
|
|
this.reset();
|
|
this.listOptions = options;
|
|
this.currList = list;
|
|
this.listArgs = listArgs;
|
|
this.cwd = workspace_1.default.cwd;
|
|
await this.getCharMap();
|
|
this.history.load();
|
|
this.window = await this.nvim.window;
|
|
this.savedHeight = await this.window.height;
|
|
this.prompt.start(options);
|
|
await this.worker.loadItems();
|
|
}
|
|
catch (e) {
|
|
await this.cancel();
|
|
let msg = e instanceof Error ? e.message : e.toString();
|
|
workspace_1.default.showMessage(`Error on "CocList ${list.name}": ${msg}`, 'error');
|
|
logger.error(e);
|
|
}
|
|
}
|
|
async resume() {
|
|
let { name, ui, currList, nvim } = this;
|
|
if (!currList)
|
|
return;
|
|
this.activated = true;
|
|
this.window = await nvim.window;
|
|
this.prompt.start();
|
|
await ui.resume(name, this.listOptions);
|
|
if (this.listOptions.autoPreview) {
|
|
await this.doAction('preview');
|
|
}
|
|
}
|
|
async doAction(name) {
|
|
let { currList } = this;
|
|
name = name || currList.defaultAction;
|
|
let action = currList.actions.find(o => o.name == name);
|
|
if (!action) {
|
|
workspace_1.default.showMessage(`Action ${name} not found`, 'error');
|
|
return;
|
|
}
|
|
let items;
|
|
if (name == 'preview') {
|
|
let item = await this.ui.item;
|
|
items = item ? [item] : [];
|
|
}
|
|
else {
|
|
items = await this.ui.getItems();
|
|
}
|
|
if (items.length)
|
|
await this.doItemAction(items, action);
|
|
}
|
|
async previous() {
|
|
let { ui } = this;
|
|
let item = ui.getItem(-1);
|
|
if (!item)
|
|
return;
|
|
ui.index = ui.index - 1;
|
|
await this.doItemAction([item], this.defaultAction);
|
|
await ui.echoMessage(item);
|
|
}
|
|
async next() {
|
|
let { ui } = this;
|
|
let item = ui.getItem(1);
|
|
if (!item)
|
|
return;
|
|
ui.index = ui.index + 1;
|
|
await this.doItemAction([item], this.defaultAction);
|
|
await ui.echoMessage(item);
|
|
}
|
|
async cancel(close = true) {
|
|
let { nvim, ui, savedHeight } = this;
|
|
if (!this.activated) {
|
|
nvim.call('coc#list#stop_prompt', [], true);
|
|
return;
|
|
}
|
|
this.activated = false;
|
|
this.worker.stop();
|
|
this.history.add();
|
|
nvim.pauseNotification();
|
|
nvim.command('pclose', true);
|
|
this.prompt.cancel();
|
|
if (close) {
|
|
ui.hide();
|
|
if (this.window) {
|
|
nvim.call('coc#list#restore', [this.window.id, savedHeight], true);
|
|
}
|
|
}
|
|
await nvim.resumeNotification();
|
|
}
|
|
async switchMatcher() {
|
|
let { matcher, interactive } = this.listOptions;
|
|
if (interactive)
|
|
return;
|
|
const list = ['fuzzy', 'strict', 'regex'];
|
|
let idx = list.indexOf(matcher) + 1;
|
|
if (idx >= list.length)
|
|
idx = 0;
|
|
this.listOptions.matcher = list[idx];
|
|
this.prompt.matcher = list[idx];
|
|
await this.worker.drawItems();
|
|
}
|
|
async togglePreview() {
|
|
let { nvim } = this;
|
|
let has = await nvim.call('coc#list#has_preview');
|
|
if (has) {
|
|
await nvim.command('pclose');
|
|
await nvim.command('redraw');
|
|
}
|
|
else {
|
|
await this.doAction('preview');
|
|
}
|
|
}
|
|
async chooseAction() {
|
|
let { nvim, currList } = this;
|
|
if (!this.activated)
|
|
return;
|
|
let { actions, defaultAction } = currList;
|
|
let names = actions.map(o => o.name);
|
|
let idx = names.indexOf(defaultAction);
|
|
if (idx != -1) {
|
|
names.splice(idx, 1);
|
|
names.unshift(defaultAction);
|
|
}
|
|
let shortcuts = new Set();
|
|
let choices = [];
|
|
for (let name of names) {
|
|
let i = 0;
|
|
for (let ch of name) {
|
|
if (!shortcuts.has(ch)) {
|
|
shortcuts.add(ch);
|
|
choices.push(`${name.slice(0, i)}&${name.slice(i)}`);
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
await nvim.call('coc#list#stop_prompt');
|
|
let n = await nvim.call('confirm', ['Choose action:', choices.join('\n')]);
|
|
await util_1.wait(10);
|
|
this.prompt.start();
|
|
if (n)
|
|
await this.doAction(names[n - 1]);
|
|
}
|
|
get name() {
|
|
let { currList } = this;
|
|
return currList ? currList.name : 'anonymous';
|
|
}
|
|
get list() {
|
|
return this.currList;
|
|
}
|
|
parseArgs(args) {
|
|
let options = [];
|
|
let interactive = false;
|
|
let autoPreview = false;
|
|
let numberSelect = false;
|
|
let name;
|
|
let input = '';
|
|
let matcher = 'fuzzy';
|
|
let position = 'bottom';
|
|
let listArgs = [];
|
|
let listOptions = [];
|
|
for (let arg of args) {
|
|
if (!name && arg.startsWith('-')) {
|
|
listOptions.push(arg);
|
|
}
|
|
else if (!name) {
|
|
if (!/^\w+$/.test(arg)) {
|
|
workspace_1.default.showMessage(`Invalid list option: "${arg}"`, 'error');
|
|
return null;
|
|
}
|
|
name = arg;
|
|
}
|
|
else {
|
|
listArgs.push(arg);
|
|
}
|
|
}
|
|
name = name || 'lists';
|
|
let config = workspace_1.default.getConfiguration(`list.source.${name}`);
|
|
if (!listOptions.length && !listArgs.length)
|
|
listOptions = config.get('defaultOptions', []);
|
|
if (!listArgs.length)
|
|
listArgs = config.get('defaultArgs', []);
|
|
for (let opt of listOptions) {
|
|
if (opt.startsWith('--input')) {
|
|
input = opt.slice(8);
|
|
}
|
|
else if (opt == '--number-select' || opt == '-N') {
|
|
numberSelect = true;
|
|
}
|
|
else if (opt == '--auto-preview' || opt == '-A') {
|
|
autoPreview = true;
|
|
}
|
|
else if (opt == '--regex' || opt == '-R') {
|
|
matcher = 'regex';
|
|
}
|
|
else if (opt == '--strict' || opt == '-S') {
|
|
matcher = 'strict';
|
|
}
|
|
else if (opt == '--interactive' || opt == '-I') {
|
|
interactive = true;
|
|
}
|
|
else if (opt == '--top') {
|
|
position = 'top';
|
|
}
|
|
else if (opt == '--tab') {
|
|
position = 'tab';
|
|
}
|
|
else if (opt == '--ignore-case' || opt == '--normal' || opt == '--no-sort') {
|
|
options.push(opt.slice(2));
|
|
}
|
|
else {
|
|
workspace_1.default.showMessage(`Invalid option "${opt}" of list`, 'error');
|
|
return null;
|
|
}
|
|
}
|
|
let list = this.listMap.get(name);
|
|
if (!list) {
|
|
workspace_1.default.showMessage(`List ${name} not found`, 'error');
|
|
return null;
|
|
}
|
|
if (interactive && !list.interactive) {
|
|
workspace_1.default.showMessage(`Interactive mode of "${name}" list not supported`, 'error');
|
|
return null;
|
|
}
|
|
return {
|
|
list,
|
|
listArgs,
|
|
options: {
|
|
numberSelect,
|
|
autoPreview,
|
|
input,
|
|
interactive,
|
|
matcher,
|
|
position,
|
|
ignorecase: options.indexOf('ignore-case') != -1 ? true : false,
|
|
mode: options.indexOf('normal') == -1 ? 'insert' : 'normal',
|
|
sort: options.indexOf('no-sort') == -1 ? true : false
|
|
},
|
|
};
|
|
}
|
|
updateStatus() {
|
|
let { ui, currList, activated, nvim } = this;
|
|
if (!activated)
|
|
return;
|
|
let buf = nvim.createBuffer(ui.bufnr);
|
|
let status = {
|
|
mode: this.prompt.mode.toUpperCase(),
|
|
args: this.args.join(' '),
|
|
name: currList.name,
|
|
total: this.worker.length,
|
|
cwd: this.cwd,
|
|
};
|
|
buf.setVar('list_status', status, true);
|
|
if (ui.window)
|
|
nvim.command('redraws', true);
|
|
}
|
|
async onInputChar(ch, charmod) {
|
|
let { mode } = this.prompt;
|
|
let mapped = this.charMap.get(ch);
|
|
let now = Date.now();
|
|
if (mapped == '<plug>' || now - this.plugTs < 2) {
|
|
this.plugTs = now;
|
|
return;
|
|
}
|
|
if (!ch)
|
|
return;
|
|
if (ch == '\x1b') {
|
|
await this.cancel();
|
|
return;
|
|
}
|
|
if (!this.activated) {
|
|
this.nvim.call('coc#list#stop_prompt', [], true);
|
|
return;
|
|
}
|
|
try {
|
|
if (mode == 'insert') {
|
|
await this.onInsertInput(ch, charmod);
|
|
}
|
|
else {
|
|
await this.onNormalInput(ch, charmod);
|
|
}
|
|
}
|
|
catch (e) {
|
|
workspace_1.default.showMessage(`Error on input ${ch}: ${e}`);
|
|
logger.error(e);
|
|
}
|
|
}
|
|
async onInsertInput(ch, charmod) {
|
|
let { nvim } = this;
|
|
let inserted = this.charMap.get(ch) || ch;
|
|
if (mouseKeys.indexOf(inserted) !== -1) {
|
|
await this.onMouseEvent(inserted);
|
|
return;
|
|
}
|
|
if (this.listOptions.numberSelect) {
|
|
let code = ch.charCodeAt(0);
|
|
if (code >= 48 && code <= 57) {
|
|
let n = Number(ch);
|
|
if (n == 0)
|
|
n = 10;
|
|
if (this.ui.length >= n) {
|
|
nvim.pauseNotification();
|
|
this.ui.setCursor(Number(ch), 0);
|
|
await nvim.resumeNotification();
|
|
await this.doAction();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
let done = await this.mappings.doInsertKeymap(inserted);
|
|
if (done || charmod || this.charMap.has(ch))
|
|
return;
|
|
for (let s of ch) {
|
|
let code = s.codePointAt(0);
|
|
if (code == 65533)
|
|
return;
|
|
// exclude control characer
|
|
if (code < 32 || code >= 127 && code <= 159)
|
|
return;
|
|
await this.prompt.acceptCharacter(s);
|
|
}
|
|
}
|
|
async onNormalInput(ch, _charmod) {
|
|
let inserted = this.charMap.get(ch) || ch;
|
|
if (mouseKeys.indexOf(inserted) !== -1) {
|
|
await this.onMouseEvent(inserted);
|
|
return;
|
|
}
|
|
let done = await this.mappings.doNormalKeymap(inserted);
|
|
if (!done)
|
|
await this.feedkeys(inserted);
|
|
}
|
|
onMouseEvent(key) {
|
|
switch (key) {
|
|
case '<LeftMouse>':
|
|
return this.ui.onMouse('mouseDown');
|
|
case '<LeftDrag>':
|
|
return this.ui.onMouse('mouseDrag');
|
|
case '<LeftRelease>':
|
|
return this.ui.onMouse('mouseUp');
|
|
case '<2-LeftMouse>':
|
|
return this.ui.onMouse('doubleClick');
|
|
}
|
|
}
|
|
async feedkeys(key) {
|
|
let { nvim } = this;
|
|
key = key.startsWith('<') && key.endsWith('>') ? `\\${key}` : key;
|
|
await nvim.call('coc#list#stop_prompt', [1]);
|
|
await nvim.eval(`feedkeys("${key}")`);
|
|
this.prompt.start();
|
|
}
|
|
async command(command) {
|
|
let { nvim } = this;
|
|
await nvim.call('coc#list#stop_prompt', [1]);
|
|
await nvim.command(command);
|
|
this.prompt.start();
|
|
}
|
|
async normal(command, bang = true) {
|
|
let { nvim } = this;
|
|
await nvim.call('coc#list#stop_prompt', [1]);
|
|
await nvim.command(`normal${bang ? '!' : ''} ${command}`);
|
|
this.prompt.start();
|
|
}
|
|
async call(fname) {
|
|
if (!this.currList || !this.window)
|
|
return;
|
|
await this.nvim.call('coc#list#stop_prompt', []);
|
|
let buf = await this.window.buffer;
|
|
let targets = await this.ui.getItems();
|
|
let context = {
|
|
name: this.currList.name,
|
|
args: this.listArgs,
|
|
input: this.prompt.input,
|
|
winid: this.window.id,
|
|
bufnr: buf.id,
|
|
targets
|
|
};
|
|
let res = await this.nvim.call(fname, [context]);
|
|
this.prompt.start();
|
|
return res;
|
|
}
|
|
async showHelp() {
|
|
// echo help
|
|
await this.cancel();
|
|
let { list, nvim } = this;
|
|
if (!list)
|
|
return;
|
|
let previewHeight = await nvim.eval('&previewheight');
|
|
nvim.pauseNotification();
|
|
nvim.command(`belowright ${previewHeight}sp +setl\\ previewwindow [LIST HELP]`, true);
|
|
nvim.command('setl nobuflisted noswapfile buftype=nofile bufhidden=wipe', true);
|
|
await nvim.resumeNotification();
|
|
let hasOptions = list.options && list.options.length;
|
|
let buf = await nvim.buffer;
|
|
let highligher = new highligher_1.default();
|
|
highligher.addLine('NAME', 'Label');
|
|
highligher.addLine(` ${list.name} - ${list.description || ''}\n`);
|
|
highligher.addLine('SYNOPSIS', 'Label');
|
|
highligher.addLine(` :CocList [LIST OPTIONS] ${list.name}${hasOptions ? ' [ARGUMENTS]' : ''}\n`);
|
|
if (list.detail) {
|
|
highligher.addLine('DESCRIPTION', 'Label');
|
|
let lines = list.detail.split('\n').map(s => ' ' + s);
|
|
highligher.addLine(lines.join('\n') + '\n');
|
|
}
|
|
if (hasOptions) {
|
|
highligher.addLine('ARGUMENTS', 'Label');
|
|
highligher.addLine('');
|
|
for (let opt of list.options) {
|
|
highligher.addLine(opt.name, 'Special');
|
|
highligher.addLine(` ${opt.description}`);
|
|
highligher.addLine('');
|
|
}
|
|
highligher.addLine('');
|
|
}
|
|
let config = workspace_1.default.getConfiguration(`list.source.${list.name}`);
|
|
if (Object.keys(config).length) {
|
|
highligher.addLine('CONFIGURATIONS', 'Label');
|
|
highligher.addLine('');
|
|
let props = {};
|
|
extensions_1.default.all.forEach(extension => {
|
|
let { packageJSON } = extension;
|
|
let { contributes } = packageJSON;
|
|
if (!contributes)
|
|
return;
|
|
let { configuration } = contributes;
|
|
if (configuration) {
|
|
let { properties } = configuration;
|
|
if (properties) {
|
|
for (let key of Object.keys(properties)) {
|
|
props[key] = properties[key];
|
|
}
|
|
}
|
|
}
|
|
});
|
|
for (let key of Object.keys(config)) {
|
|
let val = config[key];
|
|
let name = `list.source.${list.name}.${key}`;
|
|
let description = props[name] && props[name].description ? props[name].description : key;
|
|
highligher.addLine(` "${name}"`, 'MoreMsg');
|
|
highligher.addText(` - ${description}, current value: `);
|
|
highligher.addText(JSON.stringify(val), 'Special');
|
|
}
|
|
highligher.addLine('');
|
|
}
|
|
highligher.addLine('ACTIONS', 'Label');
|
|
highligher.addLine(` ${list.actions.map(o => o.name).join(', ')}`);
|
|
highligher.addLine('');
|
|
highligher.addLine(`see ':h coc-list-options' for available list options.`, 'Comment');
|
|
nvim.pauseNotification();
|
|
highligher.render(buf, 0, -1);
|
|
nvim.command('setl nomod', true);
|
|
nvim.command('setl nomodifiable', true);
|
|
nvim.command('normal! gg', true);
|
|
nvim.command('nnoremap q :bd!<CR>', true);
|
|
await nvim.resumeNotification();
|
|
}
|
|
get context() {
|
|
return {
|
|
options: this.listOptions,
|
|
args: this.listArgs,
|
|
input: this.prompt.input,
|
|
window: this.window,
|
|
listWindow: this.ui.window,
|
|
cwd: this.cwd
|
|
};
|
|
}
|
|
registerList(list) {
|
|
const { name } = list;
|
|
let exists = this.listMap.get(name);
|
|
if (this.listMap.has(name)) {
|
|
if (exists) {
|
|
if (typeof exists.dispose == 'function') {
|
|
exists.dispose();
|
|
}
|
|
this.listMap.delete(name);
|
|
}
|
|
workspace_1.default.showMessage(`list "${name}" recreated.`);
|
|
}
|
|
this.listMap.set(name, list);
|
|
extensions_1.default.addSchemeProperty(`list.source.${name}.defaultOptions`, {
|
|
type: 'array',
|
|
default: list.interactive ? ['--interactive'] : [],
|
|
description: `Default list options of "${name}" list, only used when both list option and argument are empty.`,
|
|
uniqueItems: true,
|
|
items: {
|
|
type: 'string',
|
|
enum: ['--top', '--normal', '--no-sort', '--input', '--tab',
|
|
'--strict', '--regex', '--ignore-case', '--number-select',
|
|
'--interactive', '--auto-preview']
|
|
}
|
|
});
|
|
extensions_1.default.addSchemeProperty(`list.source.${name}.defaultArgs`, {
|
|
type: 'array',
|
|
default: [],
|
|
description: `Default argument list of "${name}" list, only used when list argument is empty.`,
|
|
uniqueItems: true,
|
|
items: { type: 'string' }
|
|
});
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
if (typeof list.dispose == 'function') {
|
|
list.dispose();
|
|
}
|
|
this.listMap.delete(name);
|
|
});
|
|
}
|
|
get names() {
|
|
return Array.from(this.listMap.keys());
|
|
}
|
|
toggleMode() {
|
|
let { mode } = this.prompt;
|
|
this.prompt.mode = mode == 'normal' ? 'insert' : 'normal';
|
|
this.updateStatus();
|
|
}
|
|
getConfig(key, defaultValue) {
|
|
return this.config.get(key, defaultValue);
|
|
}
|
|
get isActivated() {
|
|
return this.activated;
|
|
}
|
|
stop() {
|
|
this.worker.stop();
|
|
}
|
|
reset() {
|
|
this.window = null;
|
|
this.listOptions = null;
|
|
this.prompt.reset();
|
|
this.worker.stop();
|
|
this.ui.reset();
|
|
}
|
|
dispose() {
|
|
if (this.config) {
|
|
this.config.dispose();
|
|
}
|
|
util_1.disposeAll(this.disposables);
|
|
}
|
|
async getCharMap() {
|
|
if (this.charMap)
|
|
return;
|
|
this.charMap = new Map();
|
|
let chars = await this.nvim.call('coc#list#get_chars');
|
|
Object.keys(chars).forEach(key => {
|
|
this.charMap.set(chars[key], key);
|
|
});
|
|
return;
|
|
}
|
|
async doItemAction(items, action) {
|
|
if (this.executing)
|
|
return;
|
|
this.executing = true;
|
|
let { nvim } = this;
|
|
let shouldCancel = action.persist !== true && action.name != 'preview';
|
|
try {
|
|
if (shouldCancel) {
|
|
await this.cancel();
|
|
}
|
|
else if (action.name != 'preview') {
|
|
await nvim.call('coc#list#stop_prompt');
|
|
}
|
|
if (!shouldCancel && !this.isActivated)
|
|
return;
|
|
if (action.multiple) {
|
|
await Promise.resolve(action.execute(items, this.context));
|
|
}
|
|
else if (action.parallel) {
|
|
await Promise.all(items.map(item => {
|
|
return Promise.resolve(action.execute(item, this.context));
|
|
}));
|
|
}
|
|
else {
|
|
for (let item of items) {
|
|
await Promise.resolve(action.execute(item, this.context));
|
|
}
|
|
}
|
|
if (!shouldCancel) {
|
|
if (!this.isActivated) {
|
|
this.nvim.command('pclose', true);
|
|
return;
|
|
}
|
|
nvim.pauseNotification();
|
|
if (action.name != 'preview') {
|
|
this.prompt.start();
|
|
}
|
|
this.ui.restoreWindow();
|
|
nvim.resumeNotification(false, true).logError();
|
|
if (action.reload)
|
|
await this.worker.loadItems(true);
|
|
}
|
|
}
|
|
catch (e) {
|
|
// tslint:disable-next-line: no-console
|
|
console.error(e);
|
|
if (!shouldCancel && this.activated) {
|
|
this.prompt.start();
|
|
}
|
|
}
|
|
this.executing = false;
|
|
}
|
|
async resolveItem() {
|
|
if (!this.activated)
|
|
return;
|
|
let index = this.ui.index;
|
|
let item = this.ui.getItem(0);
|
|
if (!item || item.resolved)
|
|
return;
|
|
let { list } = this;
|
|
if (typeof list.resolveItem == 'function') {
|
|
let resolved = await list.resolveItem(item);
|
|
if (resolved && index == this.ui.index) {
|
|
await this.ui.updateItem(resolved, index);
|
|
}
|
|
}
|
|
}
|
|
get defaultAction() {
|
|
let { currList } = this;
|
|
let { defaultAction } = currList;
|
|
return currList.actions.find(o => o.name == defaultAction);
|
|
}
|
|
}
|
|
exports.ListManager = ListManager;
|
|
exports.default = new ListManager();
|
|
//# sourceMappingURL=manager.js.map
|
|
|
|
/***/ }),
|
|
/* 365 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
exports.validKeys = [
|
|
'<esc>',
|
|
'<tab>',
|
|
'<s-tab>',
|
|
'<bs>',
|
|
'<right>',
|
|
'<left>',
|
|
'<up>',
|
|
'<down>',
|
|
'<home>',
|
|
'<end>',
|
|
'<cr>',
|
|
'<FocusGained>',
|
|
'<ScrollWheelUp>',
|
|
'<ScrollWheelDown>',
|
|
'<LeftMouse>',
|
|
'<LeftDrag>',
|
|
'<LeftRelease>',
|
|
'<2-LeftMouse>',
|
|
'<C-a>',
|
|
'<C-b>',
|
|
'<C-c>',
|
|
'<C-d>',
|
|
'<C-e>',
|
|
'<C-f>',
|
|
'<C-g>',
|
|
'<C-h>',
|
|
'<C-i>',
|
|
'<C-j>',
|
|
'<C-k>',
|
|
'<C-l>',
|
|
'<C-m>',
|
|
'<C-n>',
|
|
'<C-o>',
|
|
'<C-p>',
|
|
'<C-q>',
|
|
'<C-r>',
|
|
'<C-s>',
|
|
'<C-t>',
|
|
'<C-u>',
|
|
'<C-v>',
|
|
'<C-w>',
|
|
'<C-x>',
|
|
'<C-y>',
|
|
'<C-z>',
|
|
'<A-a>',
|
|
'<A-b>',
|
|
'<A-c>',
|
|
'<A-d>',
|
|
'<A-e>',
|
|
'<A-f>',
|
|
'<A-g>',
|
|
'<A-h>',
|
|
'<A-i>',
|
|
'<A-j>',
|
|
'<A-k>',
|
|
'<A-l>',
|
|
'<A-m>',
|
|
'<A-n>',
|
|
'<A-o>',
|
|
'<A-p>',
|
|
'<A-q>',
|
|
'<A-r>',
|
|
'<A-s>',
|
|
'<A-t>',
|
|
'<A-u>',
|
|
'<A-v>',
|
|
'<A-w>',
|
|
'<A-x>',
|
|
'<A-y>',
|
|
'<A-z>',
|
|
];
|
|
class ListConfiguration {
|
|
constructor() {
|
|
this.configuration = workspace_1.default.getConfiguration('list');
|
|
this.disposable = workspace_1.default.onDidChangeConfiguration(e => {
|
|
if (e.affectsConfiguration('list')) {
|
|
this.configuration = workspace_1.default.getConfiguration('list');
|
|
}
|
|
});
|
|
}
|
|
get(key, defaultValue) {
|
|
return this.configuration.get(key, defaultValue);
|
|
}
|
|
get previousKey() {
|
|
return this.fixKey(this.configuration.get('previousKeymap', '<C-j>'));
|
|
}
|
|
get nextKey() {
|
|
return this.fixKey(this.configuration.get('nextKeymap', '<C-k>'));
|
|
}
|
|
dispose() {
|
|
this.disposable.dispose();
|
|
}
|
|
fixKey(key) {
|
|
if (exports.validKeys.indexOf(key) !== -1)
|
|
return key;
|
|
let find = exports.validKeys.find(s => s.toLowerCase() == key.toLowerCase());
|
|
if (find)
|
|
return find;
|
|
workspace_1.default.showMessage(`Configured key "${key}" invalid.`, 'error');
|
|
return null;
|
|
}
|
|
}
|
|
exports.default = ListConfiguration;
|
|
//# sourceMappingURL=configuration.js.map
|
|
|
|
/***/ }),
|
|
/* 366 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const fuzzy_1 = __webpack_require__(367);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('list-history');
|
|
class History {
|
|
constructor(manager) {
|
|
this.manager = manager;
|
|
this.index = -1;
|
|
this.loaded = [];
|
|
this.current = [];
|
|
this.db = workspace_1.default.createDatabase('history');
|
|
let { prompt } = manager;
|
|
prompt.onDidChangeInput(input => {
|
|
if (input == this.curr)
|
|
return;
|
|
let codes = fuzzy_1.getCharCodes(input);
|
|
this.current = this.loaded.filter(s => fuzzy_1.fuzzyMatch(codes, s));
|
|
this.index = -1;
|
|
});
|
|
}
|
|
get curr() {
|
|
return this.index == -1 ? null : this.current[this.index];
|
|
}
|
|
load() {
|
|
let { db } = this;
|
|
let { input } = this.manager.prompt;
|
|
let { name } = this.manager;
|
|
let arr = db.fetch(`${name}.${encodeURIComponent(workspace_1.default.cwd)}`);
|
|
if (!arr || !Array.isArray(arr)) {
|
|
this.loaded = [];
|
|
}
|
|
else {
|
|
this.loaded = arr;
|
|
}
|
|
this.index = -1;
|
|
this.current = this.loaded.filter(s => s.startsWith(input));
|
|
}
|
|
add() {
|
|
let { loaded, db } = this;
|
|
let { name, prompt } = this.manager;
|
|
let { input } = prompt;
|
|
if (!input || input.length < 2)
|
|
return;
|
|
let idx = loaded.indexOf(input);
|
|
if (idx != -1)
|
|
loaded.splice(idx, 1);
|
|
loaded.push(input);
|
|
if (loaded.length > 200) {
|
|
loaded = loaded.slice(-200);
|
|
}
|
|
db.push(`${name}.${encodeURIComponent(workspace_1.default.cwd)}`, loaded);
|
|
}
|
|
previous() {
|
|
let { current, index } = this;
|
|
if (!current || !current.length)
|
|
return;
|
|
if (index <= 0) {
|
|
this.index = current.length - 1;
|
|
}
|
|
else {
|
|
this.index = index - 1;
|
|
}
|
|
this.manager.prompt.input = current[this.index] || '';
|
|
}
|
|
next() {
|
|
let { current, index } = this;
|
|
if (!current || !current.length)
|
|
return;
|
|
if (index == current.length - 1) {
|
|
this.index = 0;
|
|
}
|
|
else {
|
|
this.index = index + 1;
|
|
}
|
|
this.manager.prompt.input = current[this.index] || '';
|
|
}
|
|
}
|
|
exports.default = History;
|
|
//# sourceMappingURL=history.js.map
|
|
|
|
/***/ }),
|
|
/* 367 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
function getCharCodes(str) {
|
|
let res = [];
|
|
for (let i = 0, l = str.length; i < l; i++) {
|
|
res.push(str.charCodeAt(i));
|
|
}
|
|
return res;
|
|
}
|
|
exports.getCharCodes = getCharCodes;
|
|
function wordChar(ch) {
|
|
return (ch >= 97 && ch <= 122) || (ch >= 65 && ch <= 90);
|
|
}
|
|
exports.wordChar = wordChar;
|
|
function caseMatch(input, code) {
|
|
if (input == code)
|
|
return true;
|
|
if (input >= 97 && input <= 122 && code + 32 === input)
|
|
return true;
|
|
return false;
|
|
}
|
|
exports.caseMatch = caseMatch;
|
|
function fuzzyChar(a, b) {
|
|
let ca = a.charCodeAt(0);
|
|
let cb = b.charCodeAt(0);
|
|
if (ca === cb)
|
|
return true;
|
|
if (ca >= 97 && ca <= 122 && cb + 32 === ca)
|
|
return true;
|
|
return false;
|
|
}
|
|
exports.fuzzyChar = fuzzyChar;
|
|
// upper case must match, lower case ignore case
|
|
function fuzzyMatch(needle, text) {
|
|
let totalCount = needle.length;
|
|
if (needle.length > text.length)
|
|
return false;
|
|
let i = 0;
|
|
for (let j = 0; j < text.length; j++) {
|
|
if (i === totalCount)
|
|
break;
|
|
let code = text.charCodeAt(j);
|
|
let m = needle[i];
|
|
if (code === m) {
|
|
i = i + 1;
|
|
continue;
|
|
}
|
|
// upper case match lower case
|
|
if ((m >= 97 && m <= 122) && code + 32 === m) {
|
|
i = i + 1;
|
|
continue;
|
|
}
|
|
}
|
|
return i === totalCount;
|
|
}
|
|
exports.fuzzyMatch = fuzzyMatch;
|
|
//# sourceMappingURL=fuzzy.js.map
|
|
|
|
/***/ }),
|
|
/* 368 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
__webpack_require__(309);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const configuration_1 = __webpack_require__(365);
|
|
const logger = __webpack_require__(186)('list-mappings');
|
|
class Mappings {
|
|
constructor(manager, nvim, config) {
|
|
this.manager = manager;
|
|
this.nvim = nvim;
|
|
this.config = config;
|
|
this.insertMappings = new Map();
|
|
this.normalMappings = new Map();
|
|
this.userInsertMappings = new Map();
|
|
this.userNormalMappings = new Map();
|
|
let { prompt } = manager;
|
|
this.add('insert', '<C-k>', () => {
|
|
prompt.removeTail();
|
|
});
|
|
this.add('insert', '<C-n>', () => {
|
|
manager.history.next();
|
|
});
|
|
this.add('insert', '<C-p>', () => {
|
|
manager.history.previous();
|
|
});
|
|
this.add('insert', '<C-s>', () => {
|
|
return manager.switchMatcher();
|
|
});
|
|
this.add('insert', ['<C-m>', '<cr>'], async () => {
|
|
await manager.doAction();
|
|
});
|
|
this.add('insert', ['<tab>', '<C-i>', '\t'], () => {
|
|
return manager.chooseAction();
|
|
});
|
|
this.add('insert', '<C-o>', () => {
|
|
manager.toggleMode();
|
|
});
|
|
this.add('insert', '<C-c>', async () => {
|
|
manager.stop();
|
|
manager.prompt.start();
|
|
return;
|
|
});
|
|
this.add('insert', '<esc>', () => {
|
|
return manager.cancel();
|
|
});
|
|
this.add('insert', '<C-l>', async () => {
|
|
await manager.worker.loadItems(true);
|
|
});
|
|
this.add('insert', '<left>', () => {
|
|
prompt.moveLeft();
|
|
});
|
|
this.add('insert', '<right>', () => {
|
|
prompt.moveRight();
|
|
});
|
|
this.add('insert', ['<end>', '<C-e>'], () => {
|
|
prompt.moveToEnd();
|
|
});
|
|
this.add('insert', ['<home>', '<C-a>'], () => {
|
|
prompt.moveToStart();
|
|
});
|
|
this.add('insert', ['<C-h>', '<bs>'], () => {
|
|
prompt.onBackspace();
|
|
});
|
|
this.add('insert', '<C-w>', () => {
|
|
prompt.removeWord();
|
|
});
|
|
this.add('insert', '<C-u>', () => {
|
|
prompt.removeAhead();
|
|
});
|
|
this.add('insert', '<C-r>', () => {
|
|
return prompt.insertRegister();
|
|
});
|
|
this.add('insert', '<C-d>', () => {
|
|
return manager.feedkeys('<C-d>');
|
|
});
|
|
this.add('insert', '<PageUp>', () => {
|
|
return manager.feedkeys('<PageUp>');
|
|
});
|
|
this.add('insert', '<PageDown>', () => {
|
|
return manager.feedkeys('<PageDown>');
|
|
});
|
|
this.add('insert', '<down>', () => {
|
|
return manager.normal('j');
|
|
});
|
|
this.add('insert', '<up>', () => {
|
|
return manager.normal('k');
|
|
});
|
|
this.add('insert', ['<ScrollWheelUp>'], this.doScroll.bind(this, '<ScrollWheelUp>'));
|
|
this.add('insert', ['<ScrollWheelDown>'], this.doScroll.bind(this, '<ScrollWheelDown>'));
|
|
this.add('insert', ['<C-f>'], this.doScroll.bind(this, '<C-f>'));
|
|
this.add('insert', ['<C-b>'], this.doScroll.bind(this, '<C-b>'));
|
|
this.add('normal', '<C-o>', () => {
|
|
// do nothing, avoid buffer switch by accident
|
|
});
|
|
this.add('normal', 't', () => {
|
|
return manager.doAction('tabe');
|
|
});
|
|
this.add('normal', 's', () => {
|
|
return manager.doAction('split');
|
|
});
|
|
this.add('normal', 'd', () => {
|
|
return manager.doAction('drop');
|
|
});
|
|
this.add('normal', ['<cr>', '<C-m>', '\r'], () => {
|
|
return manager.doAction();
|
|
});
|
|
this.add('normal', '<C-a>', () => {
|
|
return manager.ui.selectAll();
|
|
});
|
|
this.add('normal', ' ', () => {
|
|
return manager.ui.toggleSelection();
|
|
});
|
|
this.add('normal', 'p', () => {
|
|
return manager.togglePreview();
|
|
});
|
|
this.add('normal', ['<tab>', '\t', '<C-i>'], () => {
|
|
return manager.chooseAction();
|
|
});
|
|
this.add('normal', '<C-c>', () => {
|
|
manager.stop();
|
|
});
|
|
this.add('normal', '<esc>', () => {
|
|
return manager.cancel();
|
|
});
|
|
this.add('normal', '<C-l>', () => {
|
|
return manager.worker.loadItems(true);
|
|
});
|
|
this.add('normal', ['i', 'I', 'o', 'O', 'a', 'A'], () => {
|
|
return manager.toggleMode();
|
|
});
|
|
this.add('normal', '?', () => {
|
|
return manager.showHelp();
|
|
});
|
|
this.add('normal', ':', async () => {
|
|
await manager.cancel(false);
|
|
await nvim.eval('feedkeys(":")');
|
|
});
|
|
this.add('normal', ['<ScrollWheelUp>'], this.doScroll.bind(this, '<ScrollWheelUp>'));
|
|
this.add('normal', ['<ScrollWheelDown>'], this.doScroll.bind(this, '<ScrollWheelDown>'));
|
|
let insertMappings = this.manager.getConfig('insertMappings', {});
|
|
this.userInsertMappings = this.fixUserMappings(insertMappings);
|
|
let normalMappings = this.manager.getConfig('normalMappings', {});
|
|
this.userNormalMappings = this.fixUserMappings(normalMappings);
|
|
workspace_1.default.onDidChangeConfiguration(e => {
|
|
if (e.affectsConfiguration('list')) {
|
|
let config = workspace_1.default.getConfiguration('list');
|
|
let insertMappings = config.get('insertMappings', {});
|
|
this.userInsertMappings = this.fixUserMappings(insertMappings);
|
|
let normalMappings = config.get('normalMappings', {});
|
|
this.userNormalMappings = this.fixUserMappings(normalMappings);
|
|
}
|
|
});
|
|
}
|
|
fixUserMappings(mappings) {
|
|
let res = new Map();
|
|
for (let [key, value] of Object.entries(mappings)) {
|
|
if (key.length == 1) {
|
|
res.set(key, value);
|
|
}
|
|
else if (key.startsWith('<') && key.endsWith('>')) {
|
|
if (configuration_1.validKeys.indexOf(key) != -1) {
|
|
res.set(key, value);
|
|
}
|
|
else {
|
|
let find = false;
|
|
// tslint:disable-next-line: prefer-for-of
|
|
for (let i = 0; i < configuration_1.validKeys.length; i++) {
|
|
if (configuration_1.validKeys[i].toLowerCase() == key.toLowerCase()) {
|
|
find = true;
|
|
res.set(configuration_1.validKeys[i], value);
|
|
break;
|
|
}
|
|
}
|
|
if (!find)
|
|
workspace_1.default.showMessage(`Invalid mappings key: ${key}`, 'error');
|
|
}
|
|
}
|
|
else {
|
|
// tslint:disable-next-line: no-console
|
|
workspace_1.default.showMessage(`Invalid mappings key: ${key}`, 'error');
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
async doInsertKeymap(key) {
|
|
let nextKey = this.config.nextKey;
|
|
let previousKey = this.config.previousKey;
|
|
if (key == nextKey) {
|
|
await this.manager.normal('j');
|
|
return true;
|
|
}
|
|
if (key == previousKey) {
|
|
await this.manager.normal('k');
|
|
return true;
|
|
}
|
|
let expr = this.userInsertMappings.get(key);
|
|
if (expr) {
|
|
await this.evalExpression(expr, 'insert');
|
|
return true;
|
|
}
|
|
if (this.insertMappings.has(key)) {
|
|
let fn = this.insertMappings.get(key);
|
|
await Promise.resolve(fn());
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
async doNormalKeymap(key) {
|
|
let expr = this.userNormalMappings.get(key);
|
|
if (expr) {
|
|
await this.evalExpression(expr, 'normal');
|
|
return true;
|
|
}
|
|
if (this.normalMappings.has(key)) {
|
|
let fn = this.normalMappings.get(key);
|
|
await Promise.resolve(fn());
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
add(mode, key, fn) {
|
|
let mappings = mode == 'insert' ? this.insertMappings : this.normalMappings;
|
|
if (Array.isArray(key)) {
|
|
for (let k of key) {
|
|
mappings.set(k, fn);
|
|
}
|
|
}
|
|
else {
|
|
mappings.set(key, fn);
|
|
}
|
|
}
|
|
async onError(msg) {
|
|
let { nvim } = this;
|
|
await nvim.call('coc#list#stop_prompt', []);
|
|
workspace_1.default.showMessage(msg, 'error');
|
|
this.manager.prompt.start();
|
|
}
|
|
async evalExpression(expr, _mode) {
|
|
if (typeof expr != 'string' || expr.indexOf(':') == -1) {
|
|
await this.onError(`Invalid expression ${expr}`);
|
|
return;
|
|
}
|
|
let { manager } = this;
|
|
let { prompt } = manager;
|
|
let [key, action] = expr.split(':', 2);
|
|
if (key == 'do') {
|
|
switch (action) {
|
|
case 'switch':
|
|
await manager.switchMatcher();
|
|
return;
|
|
case 'selectall':
|
|
await manager.ui.selectAll();
|
|
return;
|
|
case 'help':
|
|
await manager.showHelp();
|
|
return;
|
|
case 'refresh':
|
|
await manager.worker.loadItems();
|
|
return;
|
|
case 'exit':
|
|
await manager.cancel(true);
|
|
return;
|
|
case 'stop':
|
|
manager.stop();
|
|
return;
|
|
case 'cancel':
|
|
await manager.cancel(false);
|
|
return;
|
|
case 'toggle':
|
|
await manager.ui.toggleSelection();
|
|
return;
|
|
case 'previous':
|
|
await manager.normal('k');
|
|
return;
|
|
case 'next':
|
|
await manager.normal('j');
|
|
return;
|
|
case 'defaultaction':
|
|
await manager.doAction();
|
|
return;
|
|
default:
|
|
await this.onError(`'${action}' not supported`);
|
|
}
|
|
}
|
|
else if (key == 'prompt') {
|
|
switch (action) {
|
|
case 'previous':
|
|
manager.history.previous();
|
|
return;
|
|
case 'next':
|
|
manager.history.next();
|
|
return;
|
|
case 'start':
|
|
return prompt.moveToStart();
|
|
case 'end':
|
|
return prompt.moveToEnd();
|
|
case 'left':
|
|
return prompt.moveLeft();
|
|
case 'right':
|
|
return prompt.moveRight();
|
|
case 'deleteforward':
|
|
return prompt.onBackspace();
|
|
case 'deletebackward':
|
|
return prompt.removeNext();
|
|
case 'removetail':
|
|
return prompt.removeTail();
|
|
case 'removeahead':
|
|
return prompt.removeAhead();
|
|
case 'insertregister':
|
|
await prompt.insertRegister();
|
|
return;
|
|
case 'paste':
|
|
await prompt.paste();
|
|
return;
|
|
default:
|
|
await this.onError(`prompt '${action}' not supported`);
|
|
}
|
|
}
|
|
else if (key == 'eval') {
|
|
await prompt.eval(action);
|
|
}
|
|
else if (key == 'command') {
|
|
await manager.command(action);
|
|
}
|
|
else if (key == 'action') {
|
|
await manager.doAction(action);
|
|
}
|
|
else if (key == 'feedkeys') {
|
|
await manager.feedkeys(action);
|
|
}
|
|
else if (key == 'normal') {
|
|
await manager.normal(action, false);
|
|
}
|
|
else if (key == 'normal!') {
|
|
await manager.normal(action, true);
|
|
}
|
|
else if (key == 'call') {
|
|
await manager.call(action);
|
|
}
|
|
else if (key == 'expr') {
|
|
let name = await manager.call(action);
|
|
if (name)
|
|
await manager.doAction(name);
|
|
}
|
|
else {
|
|
await this.onError(`Invalid expression ${expr}`);
|
|
}
|
|
}
|
|
async doScroll(key) {
|
|
await this.manager.feedkeys(key);
|
|
}
|
|
}
|
|
exports.default = Mappings;
|
|
//# sourceMappingURL=mappings.js.map
|
|
|
|
/***/ }),
|
|
/* 369 */
|
|
/***/ (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__(149);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('list-prompt');
|
|
class Prompt {
|
|
constructor(nvim, config) {
|
|
this.nvim = nvim;
|
|
this.config = config;
|
|
this.cusorIndex = 0;
|
|
this._input = '';
|
|
this._mode = 'insert';
|
|
this.interactive = false;
|
|
this.requestInput = false;
|
|
this._onDidChangeInput = new vscode_languageserver_protocol_1.Emitter();
|
|
this.onDidChangeInput = this._onDidChangeInput.event;
|
|
}
|
|
get input() {
|
|
return this._input;
|
|
}
|
|
set input(str) {
|
|
if (this._input == str)
|
|
return;
|
|
this.cusorIndex = str.length;
|
|
this._input = str;
|
|
this.drawPrompt();
|
|
this._onDidChangeInput.fire(this._input);
|
|
}
|
|
get mode() {
|
|
return this._mode;
|
|
}
|
|
set mode(val) {
|
|
if (val == this._mode)
|
|
return;
|
|
this._mode = val;
|
|
this.drawPrompt();
|
|
}
|
|
set matcher(val) {
|
|
this._matcher = val;
|
|
this.drawPrompt();
|
|
}
|
|
start(opts) {
|
|
if (opts) {
|
|
this.interactive = opts.interactive;
|
|
this.cusorIndex = opts.input.length;
|
|
this._input = opts.input;
|
|
this._mode = opts.mode;
|
|
this._matcher = opts.interactive ? '' : opts.matcher;
|
|
}
|
|
let fn = workspace_1.default.isVim ? 'coc#list#prompt_start' : 'coc#list#start_prompt';
|
|
this.nvim.call(fn, [], true);
|
|
this.drawPrompt();
|
|
}
|
|
cancel() {
|
|
let { nvim } = this;
|
|
nvim.command('echo ""', true);
|
|
nvim.command('redraw', true);
|
|
nvim.call('coc#list#stop_prompt', [], true);
|
|
}
|
|
reset() {
|
|
this._input = '';
|
|
this.cusorIndex = 0;
|
|
}
|
|
drawPrompt() {
|
|
let indicator = this.config.get('indicator', '>');
|
|
let { cusorIndex, interactive, input, _matcher } = this;
|
|
let cmds = ['echo ""'];
|
|
if (this.mode == 'insert') {
|
|
if (interactive) {
|
|
cmds.push(`echohl MoreMsg | echon 'INTERACTIVE ' | echohl None`);
|
|
}
|
|
else if (_matcher) {
|
|
cmds.push(`echohl MoreMsg | echon '${_matcher.toUpperCase()} ' | echohl None`);
|
|
}
|
|
cmds.push(`echohl Special | echon '${indicator} ' | echohl None`);
|
|
if (cusorIndex == input.length) {
|
|
cmds.push(`echon '${input.replace(/'/g, "''")}'`);
|
|
cmds.push(`echohl Cursor | echon ' ' | echohl None`);
|
|
}
|
|
else {
|
|
let pre = input.slice(0, cusorIndex);
|
|
if (pre)
|
|
cmds.push(`echon '${pre.replace(/'/g, "''")}'`);
|
|
cmds.push(`echohl Cursor | echon '${input[cusorIndex].replace(/'/, "''")}' | echohl None`);
|
|
let post = input.slice(cusorIndex + 1);
|
|
cmds.push(`echon '${post.replace(/'/g, "''")}'`);
|
|
}
|
|
}
|
|
else {
|
|
cmds.push(`echohl MoreMsg | echo "" | echohl None`);
|
|
}
|
|
cmds.push('redraw');
|
|
let cmd = cmds.join('|');
|
|
this.nvim.command(cmd, true);
|
|
}
|
|
moveLeft() {
|
|
if (this.cusorIndex == 0)
|
|
return;
|
|
this.cusorIndex = this.cusorIndex - 1;
|
|
this.drawPrompt();
|
|
}
|
|
moveRight() {
|
|
if (this.cusorIndex == this._input.length)
|
|
return;
|
|
this.cusorIndex = this.cusorIndex + 1;
|
|
this.drawPrompt();
|
|
}
|
|
moveToEnd() {
|
|
if (this.cusorIndex == this._input.length)
|
|
return;
|
|
this.cusorIndex = this._input.length;
|
|
this.drawPrompt();
|
|
}
|
|
moveToStart() {
|
|
if (this.cusorIndex == 0)
|
|
return;
|
|
this.cusorIndex = 0;
|
|
this.drawPrompt();
|
|
}
|
|
onBackspace() {
|
|
let { cusorIndex, input } = this;
|
|
if (cusorIndex == 0)
|
|
return;
|
|
let pre = input.slice(0, cusorIndex);
|
|
let post = input.slice(cusorIndex);
|
|
this.cusorIndex = cusorIndex - 1;
|
|
this._input = `${pre.slice(0, pre.length - 1)}${post}`;
|
|
this.drawPrompt();
|
|
this._onDidChangeInput.fire(this._input);
|
|
}
|
|
removeNext() {
|
|
let { cusorIndex, input } = this;
|
|
if (cusorIndex == input.length - 1)
|
|
return;
|
|
let pre = input.slice(0, cusorIndex);
|
|
let post = input.slice(cusorIndex + 1);
|
|
this._input = `${pre}${post}`;
|
|
this.drawPrompt();
|
|
this._onDidChangeInput.fire(this._input);
|
|
}
|
|
removeWord() {
|
|
let { cusorIndex, input } = this;
|
|
if (cusorIndex == 0)
|
|
return;
|
|
let pre = input.slice(0, cusorIndex);
|
|
let post = input.slice(cusorIndex);
|
|
let remain = pre.replace(/[\w$]+([^\w$]+)?$/, '');
|
|
this.cusorIndex = cusorIndex - (pre.length - remain.length);
|
|
this._input = `${remain}${post}`;
|
|
this.drawPrompt();
|
|
this._onDidChangeInput.fire(this._input);
|
|
}
|
|
removeTail() {
|
|
let { cusorIndex, input } = this;
|
|
if (cusorIndex == input.length)
|
|
return;
|
|
let pre = input.slice(0, cusorIndex);
|
|
this._input = pre;
|
|
this.drawPrompt();
|
|
this._onDidChangeInput.fire(this._input);
|
|
}
|
|
removeAhead() {
|
|
let { cusorIndex, input } = this;
|
|
if (cusorIndex == 0)
|
|
return;
|
|
let post = input.slice(cusorIndex);
|
|
this.cusorIndex = 0;
|
|
this._input = post;
|
|
this.drawPrompt();
|
|
this._onDidChangeInput.fire(this._input);
|
|
}
|
|
async acceptCharacter(ch) {
|
|
if (this.requestInput) {
|
|
this.requestInput = false;
|
|
if (/^[0-9a-z"%#*+/:\-.]$/.test(ch)) {
|
|
let text = await this.nvim.call('getreg', ch);
|
|
text = text.replace(/\n/g, ' ');
|
|
this.addText(text);
|
|
}
|
|
}
|
|
else {
|
|
this.addText(ch);
|
|
}
|
|
}
|
|
async insertRegister() {
|
|
this.requestInput = true;
|
|
}
|
|
async paste() {
|
|
await this.eval('@*');
|
|
}
|
|
async eval(expression) {
|
|
let { cusorIndex, input } = this;
|
|
let text = await this.nvim.eval(expression);
|
|
text = text.replace(/\n/g, '');
|
|
this.addText(text);
|
|
}
|
|
addText(text) {
|
|
let { cusorIndex, input } = this;
|
|
this.cusorIndex = cusorIndex + text.length;
|
|
let pre = input.slice(0, cusorIndex);
|
|
let post = input.slice(cusorIndex);
|
|
this._input = `${pre}${text}${post}`;
|
|
this.drawPrompt();
|
|
this._onDidChangeInput.fire(this._input);
|
|
}
|
|
}
|
|
exports.default = Prompt;
|
|
//# sourceMappingURL=prompt.js.map
|
|
|
|
/***/ }),
|
|
/* 370 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const commands_1 = tslib_1.__importDefault(__webpack_require__(232));
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const basic_1 = tslib_1.__importDefault(__webpack_require__(371));
|
|
class CommandsList extends basic_1.default {
|
|
constructor(nvim) {
|
|
super(nvim);
|
|
this.defaultAction = 'run';
|
|
this.description = 'registered commands of coc.nvim';
|
|
this.name = 'commands';
|
|
this.mru = workspace_1.default.createMru('commands');
|
|
this.addAction('run', async (item) => {
|
|
let { cmd } = item.data;
|
|
await events_1.default.fire('Command', [cmd]);
|
|
await commands_1.default.executeCommand(cmd);
|
|
await commands_1.default.addRecent(cmd);
|
|
});
|
|
}
|
|
async loadItems(_context) {
|
|
let items = [];
|
|
let list = commands_1.default.commandList;
|
|
let { titles } = commands_1.default;
|
|
let mruList = await this.mru.load();
|
|
for (let key of titles.keys()) {
|
|
items.push({
|
|
label: `${key}\t${titles.get(key)}`,
|
|
filterText: key,
|
|
data: { cmd: key, score: score(mruList, key) }
|
|
});
|
|
}
|
|
for (let o of list) {
|
|
let { id } = o;
|
|
if (!titles.has(id)) {
|
|
items.push({
|
|
label: id,
|
|
filterText: id,
|
|
data: { cmd: id, score: score(mruList, id) }
|
|
});
|
|
}
|
|
}
|
|
items.sort((a, b) => {
|
|
return b.data.score - a.data.score;
|
|
});
|
|
return items;
|
|
}
|
|
doHighlight() {
|
|
let { nvim } = this;
|
|
nvim.pauseNotification();
|
|
nvim.command('syntax match CocCommandsTitle /\\t.*$/ contained containedin=CocCommandsLine', true);
|
|
nvim.command('highlight default link CocCommandsTitle Comment', true);
|
|
nvim.resumeNotification().catch(_e => {
|
|
// noop
|
|
});
|
|
}
|
|
}
|
|
exports.default = CommandsList;
|
|
function score(list, key) {
|
|
let idx = list.indexOf(key);
|
|
return idx == -1 ? -1 : list.length - idx;
|
|
}
|
|
//# sourceMappingURL=commands.js.map
|
|
|
|
/***/ }),
|
|
/* 371 */
|
|
/***/ (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__(55));
|
|
const readline_1 = tslib_1.__importDefault(__webpack_require__(60));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const util_1 = __webpack_require__(174);
|
|
const position_1 = __webpack_require__(213);
|
|
const string_1 = __webpack_require__(210);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const configuration_1 = tslib_1.__importDefault(__webpack_require__(365));
|
|
const logger = __webpack_require__(186)('list-basic');
|
|
class BasicList {
|
|
constructor(nvim) {
|
|
this.nvim = nvim;
|
|
this.defaultAction = 'open';
|
|
this.actions = [];
|
|
this.options = [];
|
|
this.disposables = [];
|
|
this.config = new configuration_1.default();
|
|
}
|
|
get hlGroup() {
|
|
return this.config.get('previewHighlightGroup', 'Search');
|
|
}
|
|
get previewHeight() {
|
|
return this.config.get('maxPreviewHeight', 12);
|
|
}
|
|
get splitRight() {
|
|
return this.config.get('previewSplitRight', false);
|
|
}
|
|
parseArguments(args) {
|
|
if (!this.optionMap) {
|
|
this.optionMap = new Map();
|
|
for (let opt of this.options) {
|
|
let parts = opt.name.split(/,\s*/g).map(s => s.replace(/\s+.*/g, ''));
|
|
let name = opt.key ? opt.key : parts[parts.length - 1].replace(/^-/, '');
|
|
for (let p of parts) {
|
|
this.optionMap.set(p, { name, hasValue: opt.hasValue });
|
|
}
|
|
}
|
|
}
|
|
let res = {};
|
|
for (let i = 0; i < args.length; i++) {
|
|
let arg = args[i];
|
|
let def = this.optionMap.get(arg);
|
|
if (!def) {
|
|
logger.error(`Option "${arg}" of "${this.name}" not found`);
|
|
continue;
|
|
}
|
|
let value = true;
|
|
if (def.hasValue) {
|
|
value = args[i + 1] || '';
|
|
i = i + 1;
|
|
}
|
|
res[def.name] = value;
|
|
}
|
|
return res;
|
|
}
|
|
getConfig() {
|
|
return workspace_1.default.getConfiguration(`list.source.${this.name}`);
|
|
}
|
|
addAction(name, fn, options) {
|
|
this.createAction(Object.assign({
|
|
name,
|
|
execute: fn
|
|
}, options || {}));
|
|
}
|
|
addMultipleAction(name, fn, options) {
|
|
this.createAction(Object.assign({
|
|
name,
|
|
multiple: true,
|
|
execute: fn
|
|
}, options || {}));
|
|
}
|
|
addLocationActions() {
|
|
this.createAction({
|
|
name: 'preview',
|
|
execute: async (item, context) => {
|
|
let loc = await this.convertLocation(item.location);
|
|
await this.previewLocation(loc, context);
|
|
}
|
|
});
|
|
let { nvim } = this;
|
|
this.createAction({
|
|
name: 'quickfix',
|
|
multiple: true,
|
|
execute: async (items) => {
|
|
let quickfixItems = await Promise.all(items.map(item => {
|
|
return this.convertLocation(item.location).then(loc => {
|
|
return workspace_1.default.getQuickfixItem(loc);
|
|
});
|
|
}));
|
|
await nvim.call('setqflist', [quickfixItems]);
|
|
let openCommand = await nvim.getVar('coc_quickfix_open_command');
|
|
nvim.command(typeof openCommand === 'string' ? openCommand : 'copen', true);
|
|
}
|
|
});
|
|
for (let name of ['open', 'tabe', 'drop', 'vsplit', 'split']) {
|
|
this.createAction({
|
|
name,
|
|
execute: async (item) => {
|
|
await this.jumpTo(item.location, name == 'open' ? null : name);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
async convertLocation(location) {
|
|
if (typeof location == 'string')
|
|
return vscode_languageserver_protocol_1.Location.create(location, vscode_languageserver_protocol_1.Range.create(0, 0, 0, 0));
|
|
if (vscode_languageserver_protocol_1.Location.is(location))
|
|
return location;
|
|
let u = vscode_uri_1.URI.parse(location.uri);
|
|
if (u.scheme != 'file')
|
|
return vscode_languageserver_protocol_1.Location.create(location.uri, vscode_languageserver_protocol_1.Range.create(0, 0, 0, 0));
|
|
const rl = readline_1.default.createInterface({
|
|
input: fs_1.default.createReadStream(u.fsPath, { encoding: 'utf8' }),
|
|
});
|
|
let match = location.line;
|
|
let n = 0;
|
|
let resolved = false;
|
|
let line = await new Promise(resolve => {
|
|
rl.on('line', line => {
|
|
if (resolved)
|
|
return;
|
|
if (line.indexOf(match) !== -1) {
|
|
rl.removeAllListeners();
|
|
rl.close();
|
|
resolved = true;
|
|
resolve(line);
|
|
return;
|
|
}
|
|
n = n + 1;
|
|
});
|
|
rl.on('error', e => {
|
|
this.nvim.errWriteLine(`Read ${u.fsPath} error: ${e.message}`);
|
|
resolve(null);
|
|
});
|
|
});
|
|
if (line != null) {
|
|
let character = location.text ? line.indexOf(location.text) : 0;
|
|
if (character == 0)
|
|
character = line.match(/^\s*/)[0].length;
|
|
let end = vscode_languageserver_protocol_1.Position.create(n, character + (location.text ? location.text.length : 0));
|
|
return vscode_languageserver_protocol_1.Location.create(location.uri, vscode_languageserver_protocol_1.Range.create(vscode_languageserver_protocol_1.Position.create(n, character), end));
|
|
}
|
|
return vscode_languageserver_protocol_1.Location.create(location.uri, vscode_languageserver_protocol_1.Range.create(0, 0, 0, 0));
|
|
}
|
|
async jumpTo(location, command) {
|
|
if (typeof location == 'string') {
|
|
await workspace_1.default.jumpTo(location, null, command);
|
|
return;
|
|
}
|
|
let { range, uri } = await this.convertLocation(location);
|
|
let position = range.start;
|
|
if (position.line == 0 && position.character == 0 && position_1.comparePosition(position, range.end) == 0) {
|
|
// allow plugin that remember position.
|
|
position = null;
|
|
}
|
|
await workspace_1.default.jumpTo(uri, position, command);
|
|
}
|
|
createAction(action) {
|
|
let { name } = action;
|
|
let idx = this.actions.findIndex(o => o.name == name);
|
|
// allow override
|
|
if (idx !== -1)
|
|
this.actions.splice(idx, 1);
|
|
this.actions.push(action);
|
|
}
|
|
async previewLocation(location, context) {
|
|
let { nvim } = this;
|
|
let { uri, range } = location;
|
|
let lineCount = Infinity;
|
|
let doc = workspace_1.default.getDocument(location.uri);
|
|
if (doc)
|
|
lineCount = doc.lineCount;
|
|
let height = Math.min(this.previewHeight, lineCount);
|
|
let u = vscode_uri_1.URI.parse(uri);
|
|
// handle different scheme
|
|
if (u.scheme == 'untitled' || u.scheme == 'unknown') {
|
|
let bufnr = parseInt(u.path, 10);
|
|
let valid = await nvim.call('bufloaded', [bufnr]);
|
|
let lnum = location.range.start.line + 1;
|
|
if (valid) {
|
|
let name = await nvim.call('bufname', [bufnr]);
|
|
name = name || '[No Name]';
|
|
let filetype = await nvim.call('getbufvar', [bufnr, '&filetype']);
|
|
let lines = await nvim.call('getbufline', [bufnr, 1, '$']);
|
|
await this.preview({ bufname: name, sketch: true, filetype: filetype || 'txt', lnum, lines }, context);
|
|
}
|
|
else {
|
|
await this.preview({ sketch: true, filetype: 'txt', lines: [] }, context);
|
|
}
|
|
return;
|
|
}
|
|
// check
|
|
let filepath = u.scheme == 'file' ? u.fsPath : u.toString();
|
|
nvim.pauseNotification();
|
|
nvim.call('fnameescape', filepath, true);
|
|
nvim.call('buflisted', filepath, true);
|
|
nvim.call('eval', `!empty(getwininfo(${context.window.id}))`, true);
|
|
let [res, error] = await nvim.resumeNotification();
|
|
if (error) {
|
|
logger.error(error);
|
|
return;
|
|
}
|
|
// open previewwindow
|
|
let { position } = context.options;
|
|
let [escaped, exists, valid] = res;
|
|
let lnum = range.start.line + 1;
|
|
let winid = context.listWindow.id;
|
|
nvim.pauseNotification();
|
|
nvim.command('pclose', true);
|
|
if (this.splitRight || position == 'tab') {
|
|
if (valid && this.splitRight)
|
|
nvim.call('win_gotoid', [context.window.id], true);
|
|
nvim.command(`silent belowright vs +setl\\ previewwindow ${escaped}`, true);
|
|
}
|
|
else {
|
|
let mod = context.options.position == 'top' ? 'below' : 'above';
|
|
nvim.command(`silent ${mod} ${height}sp +setl\\ previewwindow ${escaped}`, true);
|
|
nvim.command(`exe "normal! z${height}\\<cr>"`, true);
|
|
}
|
|
nvim.command(`exe ${lnum}`, true);
|
|
nvim.command('setl winfixheight nofoldenable', true);
|
|
// highlight range
|
|
if (position_1.comparePosition(range.start, range.end) !== 0) {
|
|
let arr = [];
|
|
for (let i = range.start.line; i <= range.end.line; i++) {
|
|
let curr = await workspace_1.default.getLine(uri, range.start.line);
|
|
let sc = i == range.start.line ? range.start.character : 0;
|
|
let ec = i == range.end.line ? range.end.character : curr.length;
|
|
if (sc == ec)
|
|
continue;
|
|
arr.push(vscode_languageserver_protocol_1.Range.create(i, sc, i, ec));
|
|
}
|
|
for (let r of arr) {
|
|
let line = await workspace_1.default.getLine(uri, r.start.line);
|
|
let start = string_1.byteIndex(line, r.start.character) + 1;
|
|
let end = string_1.byteIndex(line, r.end.character) + 1;
|
|
nvim.call('matchaddpos', [this.hlGroup, [[lnum, start, end - start]]], true);
|
|
}
|
|
}
|
|
if (!exists)
|
|
nvim.command('setl nobuflisted bufhidden=wipe', true);
|
|
nvim.command('normal! zz', true);
|
|
nvim.call('win_gotoid', [winid], true);
|
|
if (workspace_1.default.isVim)
|
|
nvim.command('redraw', true);
|
|
let [, err] = await nvim.resumeNotification();
|
|
// tslint:disable-next-line: no-console
|
|
if (err)
|
|
console.error(`Error on ${err[0]}: ${err[1]} - ${err[2]}`);
|
|
}
|
|
async preview(options, context) {
|
|
let { nvim } = this;
|
|
let { bufname, filetype, sketch, lines, lnum } = options;
|
|
if (!bufname)
|
|
sketch = true;
|
|
let mod = context.options.position == 'top' ? 'below' : 'above';
|
|
let height = Math.min(this.previewHeight, lines ? Math.max(lines.length, 1) : Infinity);
|
|
let winid = context.listWindow.id;
|
|
let valid = await context.window.valid;
|
|
nvim.pauseNotification();
|
|
nvim.command('pclose', true);
|
|
if (this.splitRight || context.options.position == 'tab') {
|
|
if (valid && this.splitRight)
|
|
nvim.call('win_gotoid', [context.window.id], true);
|
|
if (bufname) {
|
|
nvim.command(`silent belowright vs +setl\\ previewwindow ${bufname}`, true);
|
|
}
|
|
else {
|
|
nvim.command(`silent belowright vnew +setl\\ previewwindow`, true);
|
|
}
|
|
}
|
|
else {
|
|
if (bufname) {
|
|
nvim.command(`silent ${mod} ${height}sp +setl\\ previewwindow ${bufname}`, true);
|
|
}
|
|
else {
|
|
nvim.command(`silent ${mod} ${height}new +setl\\ previewwindow`, true);
|
|
}
|
|
nvim.command(`exe "normal! z${height}\\<cr>"`, true);
|
|
}
|
|
if (lines && lines.length) {
|
|
nvim.call('append', [0, lines], true);
|
|
nvim.command('normal! Gdd', true);
|
|
}
|
|
nvim.command(`exe ${lnum || 1}`, true);
|
|
nvim.command('setl winfixheight nomodifiable', true);
|
|
if (sketch)
|
|
nvim.command('setl buftype=nofile bufhidden=wipe nobuflisted', true);
|
|
if (filetype == 'detect') {
|
|
nvim.command('filetype detect', true);
|
|
}
|
|
else if (filetype) {
|
|
nvim.command(`setf ${filetype}`, true);
|
|
}
|
|
if (lnum && lnum != 1)
|
|
nvim.command('normal! zz', true);
|
|
nvim.call('win_gotoid', [winid], true);
|
|
if (workspace_1.default.isVim)
|
|
nvim.command('redraw', true);
|
|
let [, err] = await nvim.resumeNotification();
|
|
// tslint:disable-next-line: no-console
|
|
if (err)
|
|
console.error(`Error on ${err[0]}: ${err[1]} - ${err[2]}`);
|
|
}
|
|
getPreviewCommand(context) {
|
|
let { position } = context.options;
|
|
if (position == 'tab')
|
|
return `belowright vs`;
|
|
let mod = position == 'top' ? 'below' : 'above';
|
|
return `${mod} ${this.previewHeight}sp`;
|
|
}
|
|
doHighlight() {
|
|
// noop
|
|
}
|
|
dispose() {
|
|
util_1.disposeAll(this.disposables);
|
|
}
|
|
}
|
|
exports.default = BasicList;
|
|
//# sourceMappingURL=basic.js.map
|
|
|
|
/***/ }),
|
|
/* 372 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(316));
|
|
const location_1 = tslib_1.__importDefault(__webpack_require__(373));
|
|
const fs_1 = __webpack_require__(200);
|
|
const logger = __webpack_require__(186)('list-symbols');
|
|
class DiagnosticsList extends location_1.default {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.defaultAction = 'open';
|
|
this.description = 'diagnostics of current workspace';
|
|
this.name = 'diagnostics';
|
|
}
|
|
async loadItems(context) {
|
|
let list = manager_1.default.getDiagnosticList();
|
|
let { cwd } = context;
|
|
return list.map(item => {
|
|
let file = fs_1.isParentFolder(cwd, item.file) ? path_1.default.relative(cwd, item.file) : item.file;
|
|
return {
|
|
label: `${file}:${item.lnum}:${item.col}\t${item.severity}\t${item.message.replace(/\n/g, '')}`,
|
|
location: item.location
|
|
};
|
|
});
|
|
}
|
|
doHighlight() {
|
|
let { nvim } = this;
|
|
nvim.pauseNotification();
|
|
nvim.command('syntax match CocDiagnosticsFile /\\v^\\s*\\S+/ contained containedin=CocDiagnosticsLine', true);
|
|
nvim.command('syntax match CocDiagnosticsError /\\tError\\t/ contained containedin=CocDiagnosticsLine', true);
|
|
nvim.command('syntax match CocDiagnosticsWarning /\\tWarning\\t/ contained containedin=CocDiagnosticsLine', true);
|
|
nvim.command('syntax match CocDiagnosticsInfo /\\tInformation\\t/ contained containedin=CocDiagnosticsLine', true);
|
|
nvim.command('syntax match CocDiagnosticsHint /\\tHint\\t/ contained containedin=CocDiagnosticsLine', true);
|
|
nvim.command('highlight default link CocDiagnosticsFile Comment', true);
|
|
nvim.command('highlight default link CocDiagnosticsError CocErrorSign', true);
|
|
nvim.command('highlight default link CocDiagnosticsWarning CocWarningSign', true);
|
|
nvim.command('highlight default link CocDiagnosticsInfo CocInfoSign', true);
|
|
nvim.command('highlight default link CocDiagnosticsHint CocHintSign', true);
|
|
nvim.resumeNotification().catch(_e => {
|
|
// noop
|
|
});
|
|
}
|
|
}
|
|
exports.default = DiagnosticsList;
|
|
//# sourceMappingURL=diagnostics.js.map
|
|
|
|
/***/ }),
|
|
/* 373 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const vscode_languageserver_types_1 = __webpack_require__(161);
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const basic_1 = tslib_1.__importDefault(__webpack_require__(371));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const fs_1 = __webpack_require__(200);
|
|
const logger = __webpack_require__(186)('list-location');
|
|
class LocationList extends basic_1.default {
|
|
constructor(nvim) {
|
|
super(nvim);
|
|
this.defaultAction = 'open';
|
|
this.description = 'show locations saved by g:coc_jump_locations variable';
|
|
this.name = 'location';
|
|
this.addLocationActions();
|
|
}
|
|
async loadItems(context) {
|
|
// filename, lnum, col, text, type
|
|
let locs = await this.nvim.getVar('coc_jump_locations');
|
|
locs = locs || [];
|
|
locs.forEach(loc => {
|
|
if (!loc.uri) {
|
|
let fullpath = path_1.default.isAbsolute(loc.filename) ? loc.filename : path_1.default.join(context.cwd, loc.filename);
|
|
loc.uri = vscode_uri_1.URI.file(fullpath).toString();
|
|
}
|
|
if (!loc.bufnr && workspace_1.default.getDocument(loc.uri) != null) {
|
|
loc.bufnr = workspace_1.default.getDocument(loc.uri).bufnr;
|
|
}
|
|
if (!loc.range) {
|
|
let { lnum, col } = loc;
|
|
loc.range = vscode_languageserver_types_1.Range.create(lnum - 1, col - 1, lnum - 1, col - 1);
|
|
}
|
|
else {
|
|
loc.lnum = loc.lnum || loc.range.start.line + 1;
|
|
loc.col = loc.col || loc.range.start.character + 1;
|
|
}
|
|
});
|
|
let bufnr = await this.nvim.call('bufnr', '%');
|
|
let ignoreFilepath = locs.every(o => o.bufnr && bufnr && o.bufnr == bufnr);
|
|
let items = locs.map(loc => {
|
|
let filename = ignoreFilepath ? '' : loc.filename;
|
|
let filterText = `${filename}${loc.text.trim()}`;
|
|
if (path_1.default.isAbsolute(filename)) {
|
|
filename = fs_1.isParentFolder(context.cwd, filename) ? path_1.default.relative(context.cwd, filename) : filename;
|
|
}
|
|
return {
|
|
label: `${filename} |${loc.type ? loc.type + ' ' : ''}${loc.lnum} col ${loc.col}| ${loc.text}`,
|
|
location: vscode_languageserver_types_1.Location.create(loc.uri, loc.range),
|
|
filterText
|
|
};
|
|
});
|
|
return items;
|
|
}
|
|
doHighlight() {
|
|
let { nvim } = this;
|
|
nvim.pauseNotification();
|
|
nvim.command('syntax match CocLocationName /\\v^[^|]+/ contained containedin=CocLocationLine', true);
|
|
nvim.command('syntax match CocLocationPosition /\\v\\|\\w*\\s?\\d+\\scol\\s\\d+\\|/ contained containedin=CocLocationLine', true);
|
|
nvim.command('syntax match CocLocationError /Error/ contained containedin=CocLocationPosition', true);
|
|
nvim.command('syntax match CocLocationWarning /Warning/ contained containedin=CocLocationPosition', true);
|
|
nvim.command('highlight default link CocLocationName Directory', true);
|
|
nvim.command('highlight default link CocLocationPosition LineNr', true);
|
|
nvim.command('highlight default link CocLocationError Error', true);
|
|
nvim.command('highlight default link CocLocationWarning WarningMsg', true);
|
|
nvim.resumeNotification().catch(_e => {
|
|
// noop
|
|
});
|
|
}
|
|
}
|
|
exports.default = LocationList;
|
|
//# sourceMappingURL=location.js.map
|
|
|
|
/***/ }),
|
|
/* 374 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const os_1 = tslib_1.__importDefault(__webpack_require__(56));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const extensions_1 = tslib_1.__importDefault(__webpack_require__(238));
|
|
const util_1 = __webpack_require__(174);
|
|
const fs_1 = __webpack_require__(200);
|
|
const basic_1 = tslib_1.__importDefault(__webpack_require__(371));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('list-extensions');
|
|
class ExtensionList extends basic_1.default {
|
|
constructor(nvim) {
|
|
super(nvim);
|
|
this.defaultAction = 'toggle';
|
|
this.description = 'manage coc extensions';
|
|
this.name = 'extensions';
|
|
this.addAction('toggle', async (item) => {
|
|
let { id, state } = item.data;
|
|
if (state == 'disabled')
|
|
return;
|
|
if (state == 'activated') {
|
|
extensions_1.default.deactivate(id);
|
|
}
|
|
else {
|
|
extensions_1.default.activate(id);
|
|
}
|
|
await util_1.wait(100);
|
|
}, { persist: true, reload: true, parallel: true });
|
|
this.addAction('disable', async (item) => {
|
|
let { id, state } = item.data;
|
|
if (state !== 'disabled')
|
|
await extensions_1.default.toggleExtension(id);
|
|
}, { persist: true, reload: true, parallel: true });
|
|
this.addAction('enable', async (item) => {
|
|
let { id, state } = item.data;
|
|
if (state == 'disabled')
|
|
await extensions_1.default.toggleExtension(id);
|
|
}, { persist: true, reload: true, parallel: true });
|
|
this.addAction('lock', async (item) => {
|
|
let { id } = item.data;
|
|
await extensions_1.default.toggleLock(id);
|
|
}, { persist: true, reload: true });
|
|
this.addAction('doc', async (item) => {
|
|
let { root } = item.data;
|
|
let files = await fs_1.readdirAsync(root);
|
|
let file = files.find(f => /^readme/i.test(f));
|
|
if (file) {
|
|
let escaped = await nvim.call('fnameescape', [path_1.default.join(root, file)]);
|
|
await workspace_1.default.callAsync('coc#util#execute', [`edit ${escaped}`]);
|
|
}
|
|
});
|
|
this.addAction('reload', async (item) => {
|
|
let { id, state } = item.data;
|
|
if (state == 'disabled')
|
|
return;
|
|
if (state == 'activated') {
|
|
extensions_1.default.deactivate(id);
|
|
}
|
|
extensions_1.default.activate(id);
|
|
await util_1.wait(100);
|
|
}, { persist: true, reload: true });
|
|
this.addMultipleAction('uninstall', async (items) => {
|
|
let ids = [];
|
|
for (let item of items) {
|
|
if (item.data.isLocal)
|
|
continue;
|
|
ids.push(item.data.id);
|
|
}
|
|
extensions_1.default.uninstallExtension(ids).catch(e => {
|
|
logger.error(e);
|
|
});
|
|
});
|
|
}
|
|
async loadItems(_context) {
|
|
let items = [];
|
|
let list = await extensions_1.default.getExtensionStates();
|
|
let lockedList = await extensions_1.default.getLockedList();
|
|
for (let stat of list) {
|
|
let prefix = '+';
|
|
if (stat.state == 'disabled') {
|
|
prefix = '-';
|
|
}
|
|
else if (stat.state == 'activated') {
|
|
prefix = '*';
|
|
}
|
|
else if (stat.state == 'unknown') {
|
|
prefix = '?';
|
|
}
|
|
let root = await this.nvim.call('resolve', stat.root);
|
|
let locked = lockedList.indexOf(stat.id) !== -1;
|
|
items.push({
|
|
label: `${prefix} ${stat.id}${locked ? ' ' : ''}\t${stat.isLocal ? '[RTP]\t' : ''}${stat.version}\t${root.replace(os_1.default.homedir(), '~')}`,
|
|
filterText: stat.id,
|
|
data: {
|
|
id: stat.id,
|
|
root,
|
|
state: stat.state,
|
|
isLocal: stat.isLocal,
|
|
priority: getPriority(stat.state)
|
|
}
|
|
});
|
|
}
|
|
items.sort((a, b) => {
|
|
if (a.data.priority != b.data.priority) {
|
|
return b.data.priority - a.data.priority;
|
|
}
|
|
return b.data.id - a.data.id ? 1 : -1;
|
|
});
|
|
return items;
|
|
}
|
|
doHighlight() {
|
|
let { nvim } = this;
|
|
nvim.pauseNotification();
|
|
nvim.command('syntax match CocExtensionsActivited /\\v^\\*/ contained containedin=CocExtensionsLine', true);
|
|
nvim.command('syntax match CocExtensionsLoaded /\\v^\\+/ contained containedin=CocExtensionsLine', true);
|
|
nvim.command('syntax match CocExtensionsDisabled /\\v^-/ contained containedin=CocExtensionsLine', true);
|
|
nvim.command('syntax match CocExtensionsName /\\v%3c\\S+/ contained containedin=CocExtensionsLine', true);
|
|
nvim.command('syntax match CocExtensionsRoot /\\v\\t[^\\t]*$/ contained containedin=CocExtensionsLine', true);
|
|
nvim.command('syntax match CocExtensionsLocal /\\v\\[RTP\\]/ contained containedin=CocExtensionsLine', true);
|
|
nvim.command('highlight default link CocExtensionsActivited Special', true);
|
|
nvim.command('highlight default link CocExtensionsLoaded Normal', true);
|
|
nvim.command('highlight default link CocExtensionsDisabled Comment', true);
|
|
nvim.command('highlight default link CocExtensionsName String', true);
|
|
nvim.command('highlight default link CocExtensionsLocal MoreMsg', true);
|
|
nvim.command('highlight default link CocExtensionsRoot Comment', true);
|
|
nvim.resumeNotification().catch(_e => {
|
|
// noop
|
|
});
|
|
}
|
|
}
|
|
exports.default = ExtensionList;
|
|
function getPriority(stat) {
|
|
switch (stat) {
|
|
case 'unknown':
|
|
return 2;
|
|
case 'activated':
|
|
return 1;
|
|
case 'disabled':
|
|
return -1;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
//# sourceMappingURL=extensions.js.map
|
|
|
|
/***/ }),
|
|
/* 375 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const fs_1 = __webpack_require__(200);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const basic_1 = tslib_1.__importDefault(__webpack_require__(371));
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const util_1 = __webpack_require__(174);
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
class FoldList extends basic_1.default {
|
|
constructor(nvim) {
|
|
super(nvim);
|
|
this.defaultAction = 'edit';
|
|
this.description = 'list of current workspace folders';
|
|
this.name = 'folders';
|
|
this.addAction('edit', async (item) => {
|
|
let newPath = await nvim.call('input', ['Folder: ', item.label, 'file']);
|
|
let stat = await fs_1.statAsync(newPath);
|
|
if (!stat || !stat.isDirectory()) {
|
|
await nvim.command(`echoerr "invalid path: ${newPath}"`);
|
|
return;
|
|
}
|
|
workspace_1.default.renameWorkspaceFolder(item.label, newPath);
|
|
}, { reload: true, persist: true });
|
|
this.addAction('delete', async (item) => {
|
|
workspace_1.default.removeWorkspaceFolder(item.label);
|
|
}, { reload: true, persist: true });
|
|
this.addAction('newfile', async (item) => {
|
|
let file = await workspace_1.default.requestInput('File name', item.label + '/');
|
|
let dir = path_1.default.dirname(file);
|
|
let stat = await fs_1.statAsync(dir);
|
|
if (!stat || !stat.isDirectory()) {
|
|
let success = await util_1.mkdirp(dir);
|
|
if (!success) {
|
|
util_1.echoErr(nvim, `Error creating new directory ${dir}`);
|
|
return;
|
|
}
|
|
}
|
|
await workspace_1.default.createFile(file, { overwrite: false, ignoreIfExists: true });
|
|
await this.jumpTo(vscode_uri_1.URI.file(file).toString());
|
|
});
|
|
}
|
|
async loadItems(_context) {
|
|
return workspace_1.default.folderPaths.map(p => {
|
|
return { label: p };
|
|
});
|
|
}
|
|
}
|
|
exports.default = FoldList;
|
|
//# sourceMappingURL=folders.js.map
|
|
|
|
/***/ }),
|
|
/* 376 */
|
|
/***/ (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__(315));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const basic_1 = tslib_1.__importDefault(__webpack_require__(371));
|
|
const vscode_languageserver_types_1 = __webpack_require__(161);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const fs_1 = __webpack_require__(200);
|
|
class LinksList extends basic_1.default {
|
|
constructor(nvim) {
|
|
super(nvim);
|
|
this.defaultAction = 'open';
|
|
this.description = 'links of current buffer';
|
|
this.name = 'links';
|
|
this.addAction('open', async (item) => {
|
|
let { target } = item.data;
|
|
let uri = vscode_uri_1.URI.parse(target);
|
|
if (uri.scheme.startsWith('http')) {
|
|
await nvim.call('coc#util#open_url', target);
|
|
}
|
|
else {
|
|
await workspace_1.default.jumpTo(target);
|
|
}
|
|
});
|
|
this.addAction('jump', async (item) => {
|
|
let { location } = item.data;
|
|
await workspace_1.default.jumpTo(location.uri, location.range.start);
|
|
});
|
|
}
|
|
async loadItems(context) {
|
|
let buf = await context.window.buffer;
|
|
let doc = workspace_1.default.getDocument(buf.id);
|
|
if (!doc)
|
|
return null;
|
|
let items = [];
|
|
let links = await languages_1.default.getDocumentLinks(doc.textDocument);
|
|
if (links == null) {
|
|
throw new Error('Links provider not found.');
|
|
}
|
|
let res = [];
|
|
for (let link of links) {
|
|
if (link.target) {
|
|
items.push({
|
|
label: formatUri(link.target),
|
|
data: {
|
|
target: link.target,
|
|
location: vscode_languageserver_types_1.Location.create(doc.uri, link.range)
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
link = await languages_1.default.resolveDocumentLink(link);
|
|
if (link.target) {
|
|
items.push({
|
|
label: formatUri(link.target),
|
|
data: {
|
|
target: link.target,
|
|
location: vscode_languageserver_types_1.Location.create(doc.uri, link.range)
|
|
}
|
|
});
|
|
}
|
|
res.push(link);
|
|
}
|
|
}
|
|
return items;
|
|
}
|
|
}
|
|
exports.default = LinksList;
|
|
function formatUri(uri) {
|
|
if (!uri.startsWith('file:'))
|
|
return uri;
|
|
let filepath = vscode_uri_1.URI.parse(uri).fsPath;
|
|
return fs_1.isParentFolder(workspace_1.default.cwd, filepath) ? path_1.default.relative(workspace_1.default.cwd, filepath) : filepath;
|
|
}
|
|
//# sourceMappingURL=links.js.map
|
|
|
|
/***/ }),
|
|
/* 377 */
|
|
/***/ (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__(371));
|
|
const mru_1 = tslib_1.__importDefault(__webpack_require__(215));
|
|
class LinksList extends basic_1.default {
|
|
constructor(nvim, listMap) {
|
|
super(nvim);
|
|
this.listMap = listMap;
|
|
this.name = 'lists';
|
|
this.defaultAction = 'open';
|
|
this.description = 'registered lists of coc.nvim';
|
|
this.mru = new mru_1.default('lists');
|
|
this.addAction('open', async (item) => {
|
|
let { name } = item.data;
|
|
await this.mru.add(name);
|
|
await nvim.command(`CocList ${name}`);
|
|
});
|
|
}
|
|
async loadItems(_context) {
|
|
let items = [];
|
|
let mruList = await this.mru.load();
|
|
for (let list of this.listMap.values()) {
|
|
if (list.name == 'lists')
|
|
continue;
|
|
items.push({
|
|
label: `${list.name}\t${list.description || ''}`,
|
|
data: {
|
|
name: list.name,
|
|
interactive: list.interactive,
|
|
score: score(mruList, list.name)
|
|
}
|
|
});
|
|
}
|
|
items.sort((a, b) => {
|
|
return b.data.score - a.data.score;
|
|
});
|
|
return items;
|
|
}
|
|
doHighlight() {
|
|
let { nvim } = this;
|
|
nvim.pauseNotification();
|
|
nvim.command('syntax match CocListsDesc /\\t.*$/ contained containedin=CocListsLine', true);
|
|
nvim.command('highlight default link CocListsDesc Comment', true);
|
|
nvim.resumeNotification().catch(_e => {
|
|
// noop
|
|
});
|
|
}
|
|
}
|
|
exports.default = LinksList;
|
|
function score(list, key) {
|
|
let idx = list.indexOf(key);
|
|
return idx == -1 ? -1 : list.length - idx;
|
|
}
|
|
//# sourceMappingURL=lists.js.map
|
|
|
|
/***/ }),
|
|
/* 378 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const vscode_languageserver_types_1 = __webpack_require__(161);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const languages_1 = tslib_1.__importDefault(__webpack_require__(315));
|
|
const util_1 = __webpack_require__(174);
|
|
const fs_1 = __webpack_require__(200);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const location_1 = tslib_1.__importDefault(__webpack_require__(373));
|
|
const convert_1 = __webpack_require__(379);
|
|
const logger = __webpack_require__(186)('list-symbols');
|
|
class Outline extends location_1.default {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.description = 'symbols of current document';
|
|
this.name = 'outline';
|
|
}
|
|
async loadItems(context) {
|
|
let buf = await context.window.buffer;
|
|
let document = workspace_1.default.getDocument(buf.id);
|
|
if (!document)
|
|
return null;
|
|
let config = this.getConfig();
|
|
let ctagsFilestypes = config.get('ctagsFilestypes', []);
|
|
let symbols;
|
|
if (ctagsFilestypes.indexOf(document.filetype) == -1) {
|
|
symbols = await languages_1.default.getDocumentSymbol(document.textDocument);
|
|
}
|
|
if (!symbols)
|
|
return await this.loadCtagsSymbols(document);
|
|
if (symbols.length == 0)
|
|
return [];
|
|
let items = [];
|
|
let isSymbols = !symbols[0].hasOwnProperty('location');
|
|
if (isSymbols) {
|
|
function addSymbols(symbols, level = 0) {
|
|
symbols.sort(sortSymbols);
|
|
for (let s of symbols) {
|
|
let kind = convert_1.getSymbolKind(s.kind);
|
|
let location = vscode_languageserver_types_1.Location.create(document.uri, s.selectionRange);
|
|
items.push({
|
|
label: `${' '.repeat(level * 2)}${s.name}\t[${kind}]\t${s.range.start.line + 1}`,
|
|
filterText: s.name,
|
|
location
|
|
});
|
|
if (s.children && s.children.length) {
|
|
addSymbols(s.children, level + 1);
|
|
}
|
|
}
|
|
}
|
|
addSymbols(symbols);
|
|
}
|
|
else {
|
|
symbols.sort((a, b) => {
|
|
let sa = a.location.range.start;
|
|
let sb = b.location.range.start;
|
|
let d = sa.line - sb.line;
|
|
return d == 0 ? sa.character - sb.character : d;
|
|
});
|
|
for (let s of symbols) {
|
|
let kind = convert_1.getSymbolKind(s.kind);
|
|
if (s.name.endsWith(') callback'))
|
|
continue;
|
|
if (s.location.uri === undefined) {
|
|
s.location.uri = document.uri;
|
|
}
|
|
items.push({
|
|
label: `${s.name} [${kind}] ${s.location.range.start.line + 1}`,
|
|
filterText: `${s.name}`,
|
|
location: s.location
|
|
});
|
|
}
|
|
}
|
|
return items;
|
|
}
|
|
doHighlight() {
|
|
let { nvim } = this;
|
|
nvim.pauseNotification();
|
|
nvim.command('syntax match CocOutlineName /\\v^\\s*[^\t]+/ contained containedin=CocOutlineLine', true);
|
|
nvim.command('syntax match CocOutlineKind /\\[\\w\\+\\]/ contained containedin=CocOutlineLine', true);
|
|
nvim.command('syntax match CocOutlineLine /\\d\\+$/ contained containedin=CocOutlineLine', true);
|
|
nvim.command('highlight default link CocOutlineName Normal', true);
|
|
nvim.command('highlight default link CocOutlineKind Typedef', true);
|
|
nvim.command('highlight default link CocOutlineLine Comment', true);
|
|
nvim.resumeNotification().catch(_e => {
|
|
// noop
|
|
});
|
|
}
|
|
async loadCtagsSymbols(document) {
|
|
let uri = vscode_uri_1.URI.parse(document.uri);
|
|
let extname = path_1.default.extname(uri.fsPath);
|
|
let content = '';
|
|
let tempname = await this.nvim.call('tempname');
|
|
let filepath = `${tempname}.${extname}`;
|
|
let escaped = await this.nvim.call('fnameescape', filepath);
|
|
await fs_1.writeFile(escaped, document.getDocumentContent());
|
|
try {
|
|
content = await util_1.runCommand(`ctags -f - --excmd=number --language-force=${document.filetype} ${escaped}`);
|
|
}
|
|
catch (e) {
|
|
// noop
|
|
}
|
|
if (!content.trim().length) {
|
|
content = await util_1.runCommand(`ctags -f - --excmd=number ${escaped}`);
|
|
}
|
|
content = content.trim();
|
|
if (!content)
|
|
return [];
|
|
let lines = content.split('\n');
|
|
let items = [];
|
|
for (let line of lines) {
|
|
let parts = line.split('\t');
|
|
if (parts.length < 4)
|
|
continue;
|
|
let lnum = Number(parts[2].replace(/;"$/, ''));
|
|
let text = document.getline(lnum - 1);
|
|
if (!text)
|
|
continue;
|
|
let idx = text.indexOf(parts[0]);
|
|
let start = idx == -1 ? 0 : idx;
|
|
let range = vscode_languageserver_types_1.Range.create(lnum - 1, start, lnum - 1, start + parts[0].length);
|
|
items.push({
|
|
label: `${parts[0]} [${parts[3]}] ${lnum}`,
|
|
filterText: parts[0],
|
|
location: vscode_languageserver_types_1.Location.create(document.uri, range),
|
|
data: { line: lnum }
|
|
});
|
|
}
|
|
items.sort((a, b) => {
|
|
return a.data.line - b.data.line;
|
|
});
|
|
return items;
|
|
}
|
|
}
|
|
exports.default = Outline;
|
|
function sortSymbols(a, b) {
|
|
let ra = a.selectionRange;
|
|
let rb = b.selectionRange;
|
|
if (ra.start.line != rb.start.line) {
|
|
return ra.start.line - rb.start.line;
|
|
}
|
|
return ra.start.character - rb.start.character;
|
|
}
|
|
//# sourceMappingURL=outline.js.map
|
|
|
|
/***/ }),
|
|
/* 379 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
function getSymbolKind(kind) {
|
|
switch (kind) {
|
|
case vscode_languageserver_protocol_1.SymbolKind.File:
|
|
return 'File';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Module:
|
|
return 'Module';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Namespace:
|
|
return 'Namespace';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Package:
|
|
return 'Package';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Class:
|
|
return 'Class';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Method:
|
|
return 'Method';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Property:
|
|
return 'Property';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Field:
|
|
return 'Field';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Constructor:
|
|
return 'Constructor';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Enum:
|
|
return 'Enum';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Interface:
|
|
return 'Interface';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Function:
|
|
return 'Function';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Variable:
|
|
return 'Variable';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Constant:
|
|
return 'Constant';
|
|
case vscode_languageserver_protocol_1.SymbolKind.String:
|
|
return 'String';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Number:
|
|
return 'Number';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Boolean:
|
|
return 'Boolean';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Array:
|
|
return 'Array';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Object:
|
|
return 'Object';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Key:
|
|
return 'Key';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Null:
|
|
return 'Null';
|
|
case vscode_languageserver_protocol_1.SymbolKind.EnumMember:
|
|
return 'EnumMember';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Struct:
|
|
return 'Struct';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Event:
|
|
return 'Event';
|
|
case vscode_languageserver_protocol_1.SymbolKind.Operator:
|
|
return 'Operator';
|
|
case vscode_languageserver_protocol_1.SymbolKind.TypeParameter:
|
|
return 'TypeParameter';
|
|
default:
|
|
return 'Unknown';
|
|
}
|
|
}
|
|
exports.getSymbolKind = getSymbolKind;
|
|
//# sourceMappingURL=convert.js.map
|
|
|
|
/***/ }),
|
|
/* 380 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const basic_1 = tslib_1.__importDefault(__webpack_require__(371));
|
|
class OutputList extends basic_1.default {
|
|
constructor(nvim) {
|
|
super(nvim);
|
|
this.defaultAction = 'open';
|
|
this.name = 'output';
|
|
this.description = 'output channels of coc.nvim';
|
|
this.addAction('open', async (item) => {
|
|
workspace_1.default.showOutputChannel(item.label);
|
|
});
|
|
}
|
|
async loadItems(_context) {
|
|
let names = workspace_1.default.channelNames;
|
|
return names.map(n => {
|
|
return { label: n };
|
|
});
|
|
}
|
|
}
|
|
exports.default = OutputList;
|
|
//# sourceMappingURL=output.js.map
|
|
|
|
/***/ }),
|
|
/* 381 */
|
|
/***/ (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__(351));
|
|
const basic_1 = tslib_1.__importDefault(__webpack_require__(371));
|
|
const util_1 = __webpack_require__(174);
|
|
class ServicesList extends basic_1.default {
|
|
constructor(nvim) {
|
|
super(nvim);
|
|
this.defaultAction = 'toggle';
|
|
this.description = 'registered services of coc.nvim';
|
|
this.name = 'services';
|
|
this.addAction('toggle', async (item) => {
|
|
let { id } = item.data;
|
|
await services_1.default.toggle(id);
|
|
await util_1.wait(100);
|
|
}, { persist: true, reload: true });
|
|
}
|
|
async loadItems(_context) {
|
|
let stats = services_1.default.getServiceStats();
|
|
stats.sort((a, b) => {
|
|
return a.id > b.id ? -1 : 1;
|
|
});
|
|
return stats.map(stat => {
|
|
let prefix = stat.state == 'running' ? '*' : ' ';
|
|
return {
|
|
label: `${prefix}\t${stat.id}\t[${stat.state}]\t${stat.languageIds.join(', ')}`,
|
|
data: { id: stat.id }
|
|
};
|
|
});
|
|
}
|
|
doHighlight() {
|
|
let { nvim } = this;
|
|
nvim.pauseNotification();
|
|
nvim.command('syntax match CocServicesPrefix /\\v^./ contained containedin=CocServicesLine', true);
|
|
nvim.command('syntax match CocServicesName /\\v%3c\\S+/ contained containedin=CocServicesLine', true);
|
|
nvim.command('syntax match CocServicesStat /\\v\\t\\[\\w+\\]/ contained containedin=CocServicesLine', true);
|
|
nvim.command('syntax match CocServicesLanguages /\\v(\\])@<=.*$/ contained containedin=CocServicesLine', true);
|
|
nvim.command('highlight default link CocServicesPrefix Special', true);
|
|
nvim.command('highlight default link CocServicesName Type', true);
|
|
nvim.command('highlight default link CocServicesStat Statement', true);
|
|
nvim.command('highlight default link CocServicesLanguages Comment', true);
|
|
nvim.resumeNotification().catch(_e => {
|
|
// noop
|
|
});
|
|
}
|
|
}
|
|
exports.default = ServicesList;
|
|
//# sourceMappingURL=services.js.map
|
|
|
|
/***/ }),
|
|
/* 382 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const vscode_languageserver_types_1 = __webpack_require__(161);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const sources_1 = tslib_1.__importDefault(__webpack_require__(237));
|
|
const basic_1 = tslib_1.__importDefault(__webpack_require__(371));
|
|
class SourcesList extends basic_1.default {
|
|
constructor(nvim) {
|
|
super(nvim);
|
|
this.defaultAction = 'toggle';
|
|
this.description = 'registered completion sources';
|
|
this.name = 'sources';
|
|
this.addAction('toggle', async (item) => {
|
|
let { name } = item.data;
|
|
sources_1.default.toggleSource(name);
|
|
}, { persist: true, reload: true });
|
|
this.addAction('refresh', async (item) => {
|
|
let { name } = item.data;
|
|
await sources_1.default.refresh(name);
|
|
}, { persist: true, reload: true });
|
|
this.addAction('open', async (item) => {
|
|
let { location } = item;
|
|
if (location)
|
|
await this.jumpTo(location);
|
|
});
|
|
}
|
|
async loadItems(_context) {
|
|
let stats = sources_1.default.sourceStats();
|
|
stats.sort((a, b) => {
|
|
if (a.type != b.type)
|
|
return a.type < b.type ? 1 : -1;
|
|
return a.name > b.name ? -1 : 1;
|
|
});
|
|
return stats.map(stat => {
|
|
let prefix = stat.disabled ? ' ' : '*';
|
|
let location;
|
|
if (stat.filepath) {
|
|
location = vscode_languageserver_types_1.Location.create(vscode_uri_1.URI.file(stat.filepath).toString(), vscode_languageserver_types_1.Range.create(0, 0, 0, 0));
|
|
}
|
|
return {
|
|
label: `${prefix}\t${stat.name}\t[${stat.shortcut}]\t${stat.priority}\t${stat.filetypes.join(',')}`,
|
|
location,
|
|
data: { name: stat.name }
|
|
};
|
|
});
|
|
}
|
|
doHighlight() {
|
|
let { nvim } = this;
|
|
nvim.pauseNotification();
|
|
nvim.command('syntax match CocSourcesPrefix /\\v^./ contained containedin=CocSourcesLine', true);
|
|
nvim.command('syntax match CocSourcesName /\\v%3c\\S+/ contained containedin=CocSourcesLine', true);
|
|
nvim.command('syntax match CocSourcesType /\\v\\t\\[\\w+\\]/ contained containedin=CocSourcesLine', true);
|
|
nvim.command('syntax match CocSourcesFileTypes /\\v\\S+$/ contained containedin=CocSourcesLine', true);
|
|
nvim.command('highlight default link CocSourcesPrefix Special', true);
|
|
nvim.command('highlight default link CocSourcesName Type', true);
|
|
nvim.command('highlight default link CocSourcesFileTypes Comment', true);
|
|
nvim.command('highlight default link CocSourcesType Statement', true);
|
|
nvim.resumeNotification().catch(_e => {
|
|
// noop
|
|
});
|
|
}
|
|
}
|
|
exports.default = SourcesList;
|
|
//# sourceMappingURL=sources.js.map
|
|
|
|
/***/ }),
|
|
/* 383 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const languages_1 = tslib_1.__importDefault(__webpack_require__(315));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const location_1 = tslib_1.__importDefault(__webpack_require__(373));
|
|
const convert_1 = __webpack_require__(379);
|
|
const fs_1 = __webpack_require__(200);
|
|
const fzy_1 = __webpack_require__(384);
|
|
const logger = __webpack_require__(186)('list-symbols');
|
|
class Symbols extends location_1.default {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.interactive = true;
|
|
this.description = 'search workspace symbols';
|
|
this.detail = 'Symbols list is provided by server, it works on interactive mode only.';
|
|
this.name = 'symbols';
|
|
}
|
|
async loadItems(context) {
|
|
let buf = await context.window.buffer;
|
|
let document = workspace_1.default.getDocument(buf.id);
|
|
if (!document)
|
|
return null;
|
|
let { input } = context;
|
|
if (!context.options.interactive) {
|
|
throw new Error('Symbols only works on interactive mode');
|
|
}
|
|
let symbols = await languages_1.default.getWorkspaceSymbols(document.textDocument, input);
|
|
if (!symbols) {
|
|
throw new Error('Workspace symbols provider not found for current document');
|
|
}
|
|
let items = [];
|
|
for (let s of symbols) {
|
|
let kind = convert_1.getSymbolKind(s.kind);
|
|
let file = vscode_uri_1.URI.parse(s.location.uri).fsPath;
|
|
if (fs_1.isParentFolder(workspace_1.default.cwd, file)) {
|
|
file = path_1.default.relative(workspace_1.default.cwd, file);
|
|
}
|
|
items.push({
|
|
label: `${s.name} [${kind}]\t${file}`,
|
|
filterText: `${s.name}`,
|
|
location: s.location,
|
|
data: { original: s, kind: s.kind, file, score: fzy_1.score(input, s.name) }
|
|
});
|
|
}
|
|
items.sort((a, b) => {
|
|
if (a.data.score != b.data.score) {
|
|
return b.data.score - a.data.score;
|
|
}
|
|
if (a.data.kind != b.data.kind) {
|
|
return a.data.kind - b.data.kind;
|
|
}
|
|
return a.data.file.length - b.data.file.length;
|
|
});
|
|
return items;
|
|
}
|
|
async resolveItem(item) {
|
|
let s = item.data.original;
|
|
if (!s)
|
|
return null;
|
|
let resolved = await languages_1.default.resolveWorkspaceSymbol(s);
|
|
if (!resolved)
|
|
return null;
|
|
let kind = convert_1.getSymbolKind(resolved.kind);
|
|
let file = vscode_uri_1.URI.parse(resolved.location.uri).fsPath;
|
|
if (fs_1.isParentFolder(workspace_1.default.cwd, file)) {
|
|
file = path_1.default.relative(workspace_1.default.cwd, file);
|
|
}
|
|
return {
|
|
label: `${s.name} [${kind}]\t${file}`,
|
|
filterText: `${s.name}`,
|
|
location: s.location
|
|
};
|
|
}
|
|
doHighlight() {
|
|
let { nvim } = this;
|
|
nvim.pauseNotification();
|
|
nvim.command('syntax match CocSymbolsName /\\v^\\s*\\S+/ contained containedin=CocSymbolsLine', true);
|
|
nvim.command('syntax match CocSymbolsKind /\\[\\w\\+\\]\\t/ contained containedin=CocSymbolsLine', true);
|
|
nvim.command('syntax match CocSymbolsFile /\\S\\+$/ contained containedin=CocSymbolsLine', true);
|
|
nvim.command('highlight default link CocSymbolsName Normal', true);
|
|
nvim.command('highlight default link CocSymbolsKind Typedef', true);
|
|
nvim.command('highlight default link CocSymbolsFile Comment', true);
|
|
nvim.resumeNotification().catch(_e => {
|
|
// noop
|
|
});
|
|
}
|
|
}
|
|
exports.default = Symbols;
|
|
//# sourceMappingURL=symbols.js.map
|
|
|
|
/***/ }),
|
|
/* 384 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
let SCORE_MIN = -Infinity;
|
|
let SCORE_MAX = Infinity;
|
|
let SCORE_GAP_LEADING = -0.005;
|
|
let SCORE_GAP_TRAILING = -0.005;
|
|
let SCORE_GAP_INNER = -0.01;
|
|
let SCORE_MATCH_CONSECUTIVE = 1;
|
|
let SCORE_MATCH_SLASH = 0.9;
|
|
let SCORE_MATCH_WORD = 0.8;
|
|
let SCORE_MATCH_CAPITAL = 0.7;
|
|
let SCORE_MATCH_DOT = 0.6;
|
|
function islower(s) {
|
|
return s.toLowerCase() === s;
|
|
}
|
|
function isupper(s) {
|
|
return s.toUpperCase() === s;
|
|
}
|
|
function precompute_bonus(haystack) {
|
|
/* Which positions are beginning of words */
|
|
let m = haystack.length;
|
|
let match_bonus = new Array(m);
|
|
let last_ch = '/';
|
|
for (let i = 0; i < m; i++) {
|
|
let ch = haystack[i];
|
|
if (last_ch === '/') {
|
|
match_bonus[i] = SCORE_MATCH_SLASH;
|
|
}
|
|
else if (last_ch === '-' || last_ch === '_' || last_ch === ' ') {
|
|
match_bonus[i] = SCORE_MATCH_WORD;
|
|
}
|
|
else if (last_ch === '.') {
|
|
match_bonus[i] = SCORE_MATCH_DOT;
|
|
}
|
|
else if (islower(last_ch) && isupper(ch)) {
|
|
match_bonus[i] = SCORE_MATCH_CAPITAL;
|
|
}
|
|
else {
|
|
match_bonus[i] = 0;
|
|
}
|
|
last_ch = ch;
|
|
}
|
|
return match_bonus;
|
|
}
|
|
function compute(needle, haystack, D, M) {
|
|
let n = needle.length;
|
|
let m = haystack.length;
|
|
let lower_needle = needle.toLowerCase();
|
|
let lower_haystack = haystack.toLowerCase();
|
|
let match_bonus = precompute_bonus(haystack);
|
|
/*
|
|
* D[][] Stores the best score for this position ending with a match.
|
|
* M[][] Stores the best possible score at this position.
|
|
*/
|
|
for (let i = 0; i < n; i++) {
|
|
D[i] = new Array(m);
|
|
M[i] = new Array(m);
|
|
let prev_score = SCORE_MIN;
|
|
let gap_score = i === n - 1 ? SCORE_GAP_TRAILING : SCORE_GAP_INNER;
|
|
for (let j = 0; j < m; j++) {
|
|
if (lower_needle[i] === lower_haystack[j]) {
|
|
let score = SCORE_MIN;
|
|
if (!i) {
|
|
score = (j * SCORE_GAP_LEADING) + match_bonus[j];
|
|
}
|
|
else if (j) { /* i > 0 && j > 0*/
|
|
score = Math.max(M[i - 1][j - 1] + match_bonus[j],
|
|
/* consecutive match, doesn't stack with match_bonus */
|
|
D[i - 1][j - 1] + SCORE_MATCH_CONSECUTIVE);
|
|
}
|
|
D[i][j] = score;
|
|
M[i][j] = prev_score = Math.max(score, prev_score + gap_score);
|
|
}
|
|
else {
|
|
D[i][j] = SCORE_MIN;
|
|
M[i][j] = prev_score = prev_score + gap_score;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function score(needle, haystack) {
|
|
let n = needle.length;
|
|
let m = haystack.length;
|
|
if (!n || !m)
|
|
return SCORE_MIN;
|
|
if (n === m) {
|
|
/* Since this method can only be called with a haystack which
|
|
* matches needle. If the lengths of the strings are equal the
|
|
* strings themselves must also be equal (ignoring case).
|
|
*/
|
|
return SCORE_MAX;
|
|
}
|
|
if (m > 1024) {
|
|
/*
|
|
* Unreasonably large candidate: return no score
|
|
* If it is a valid match it will still be returned, it will
|
|
* just be ranked below any reasonably sized candidates
|
|
*/
|
|
return SCORE_MIN;
|
|
}
|
|
let D = new Array(n);
|
|
let M = new Array(n);
|
|
compute(needle, haystack, D, M);
|
|
return M[n - 1][m - 1];
|
|
}
|
|
exports.score = score;
|
|
function positions(needle, haystack) {
|
|
let n = needle.length;
|
|
let m = haystack.length;
|
|
let positions = new Array(n);
|
|
if (!n || !m)
|
|
return positions;
|
|
if (n === m) {
|
|
for (let i = 0; i < n; i++)
|
|
positions[i] = i;
|
|
return positions;
|
|
}
|
|
if (m > 1024) {
|
|
return positions;
|
|
}
|
|
let D = new Array(n);
|
|
let M = new Array(n);
|
|
compute(needle, haystack, D, M);
|
|
/* backtrack to find the positions of optimal matching */
|
|
let match_required = false;
|
|
for (let i = n - 1, j = m - 1; i >= 0; i--) {
|
|
for (; j >= 0; j--) {
|
|
/*
|
|
* There may be multiple paths which result in
|
|
* the optimal weight.
|
|
*
|
|
* For simplicity, we will pick the first one
|
|
* we encounter, the latest in the candidate
|
|
* string.
|
|
*/
|
|
if (D[i][j] !== SCORE_MIN &&
|
|
(match_required || D[i][j] === M[i][j])) {
|
|
/* If this score was determined using
|
|
* SCORE_MATCH_CONSECUTIVE, the
|
|
* previous character MUST be a match
|
|
*/
|
|
match_required =
|
|
i && j &&
|
|
M[i][j] === D[i - 1][j - 1] + SCORE_MATCH_CONSECUTIVE;
|
|
positions[i] = j--;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return positions;
|
|
}
|
|
exports.positions = positions;
|
|
function hasMatch(needle, haystack) {
|
|
needle = needle.toLowerCase();
|
|
haystack = haystack.toLowerCase();
|
|
let l = needle.length;
|
|
for (let i = 0, j = 0; i < l; i += 1) {
|
|
j = haystack.indexOf(needle[i], j) + 1;
|
|
if (j === 0)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
exports.hasMatch = hasMatch;
|
|
//# sourceMappingURL=fzy.js.map
|
|
|
|
/***/ }),
|
|
/* 385 */
|
|
/***/ (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__(149);
|
|
const commands_1 = tslib_1.__importDefault(__webpack_require__(232));
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(316));
|
|
const languages_1 = tslib_1.__importDefault(__webpack_require__(315));
|
|
const services_1 = tslib_1.__importDefault(__webpack_require__(351));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const basic_1 = tslib_1.__importDefault(__webpack_require__(371));
|
|
const logger = __webpack_require__(186)('list-actions');
|
|
class ActionsList extends basic_1.default {
|
|
constructor(nvim) {
|
|
super(nvim);
|
|
this.defaultAction = 'do';
|
|
this.description = 'code actions of selected range.';
|
|
this.name = 'actions';
|
|
this.options = [{
|
|
name: '-start',
|
|
description: 'start of line',
|
|
hasValue: true
|
|
}, {
|
|
name: '-end',
|
|
description: 'end of line',
|
|
hasValue: true
|
|
}, {
|
|
name: '-quickfix',
|
|
description: 'quickfix only',
|
|
}, {
|
|
name: '-source',
|
|
description: 'source action only'
|
|
}];
|
|
this.addAction('do', async (item) => {
|
|
let action = item.data.action;
|
|
let { command, edit } = action;
|
|
if (edit)
|
|
await workspace_1.default.applyEdit(edit);
|
|
if (command) {
|
|
if (commands_1.default.has(command.command)) {
|
|
commands_1.default.execute(command);
|
|
}
|
|
else {
|
|
let clientId = action.clientId;
|
|
let service = services_1.default.getService(clientId);
|
|
let params = {
|
|
command: command.command,
|
|
arguments: command.arguments
|
|
};
|
|
if (service.client) {
|
|
let { client } = service;
|
|
client
|
|
.sendRequest(vscode_languageserver_protocol_1.ExecuteCommandRequest.type, params)
|
|
.then(undefined, error => {
|
|
workspace_1.default.showMessage(`Execute '${command.command} error: ${error}'`, 'error');
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
async loadItems(context) {
|
|
let buf = await context.window.buffer;
|
|
let doc = workspace_1.default.getDocument(buf.id);
|
|
if (!doc)
|
|
return null;
|
|
let args = this.parseArguments(context.args);
|
|
let range;
|
|
if (args.start && args.end) {
|
|
range = vscode_languageserver_protocol_1.Range.create(parseInt(args.start, 10) - 1, 0, parseInt(args.end, 10), 0);
|
|
}
|
|
else {
|
|
range = vscode_languageserver_protocol_1.Range.create(0, 0, doc.lineCount, 0);
|
|
}
|
|
let diagnostics = manager_1.default.getDiagnosticsInRange(doc.textDocument, range);
|
|
let actionContext = { diagnostics };
|
|
if (args.quickfix) {
|
|
actionContext.only = [vscode_languageserver_protocol_1.CodeActionKind.QuickFix];
|
|
}
|
|
else if (args.source) {
|
|
actionContext.only = [vscode_languageserver_protocol_1.CodeActionKind.Source];
|
|
}
|
|
let codeActionsMap = await languages_1.default.getCodeActions(doc.textDocument, range, actionContext);
|
|
if (!codeActionsMap)
|
|
return [];
|
|
let codeActions = [];
|
|
for (let clientId of codeActionsMap.keys()) {
|
|
let actions = codeActionsMap.get(clientId);
|
|
for (let action of actions) {
|
|
codeActions.push(Object.assign({ clientId }, action));
|
|
}
|
|
}
|
|
codeActions.sort((a, b) => {
|
|
if (a.isPrefered && !b.isPrefered) {
|
|
return -1;
|
|
}
|
|
if (b.isPrefered && !a.isPrefered) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
});
|
|
let items = codeActions.map(action => {
|
|
return {
|
|
label: `${action.title} ${action.clientId ? `[${action.clientId}]` : ''} ${action.kind ? `(${action.kind})` : ''}`,
|
|
data: { action }
|
|
};
|
|
});
|
|
return items;
|
|
}
|
|
doHighlight() {
|
|
let { nvim } = this;
|
|
nvim.pauseNotification();
|
|
nvim.command('syntax match CocActionsTitle /\\v^[^[]+/ contained containedin=CocActionsLine', true);
|
|
nvim.command('syntax match CocActionsClient /\\[\\w\\+\\]/ contained containedin=CocActionsLine', true);
|
|
nvim.command('syntax match CocActionsKind /\\v\\(.*\\)$/ contained containedin=CocActionsLine', true);
|
|
nvim.command('highlight default link CocActionsTitle Normal', true);
|
|
nvim.command('highlight default link CocActionsClient Typedef', true);
|
|
nvim.command('highlight default link CocActionsKind Comment', true);
|
|
nvim.resumeNotification().catch(_e => {
|
|
// noop
|
|
});
|
|
}
|
|
}
|
|
exports.default = ActionsList;
|
|
//# sourceMappingURL=actions.js.map
|
|
|
|
/***/ }),
|
|
/* 386 */
|
|
/***/ (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__(149);
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const util_1 = __webpack_require__(174);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const debounce = __webpack_require__(176);
|
|
const logger = __webpack_require__(186)('list-ui');
|
|
class ListUI {
|
|
constructor(nvim, config) {
|
|
this.nvim = nvim;
|
|
this.config = config;
|
|
this.newTab = false;
|
|
this._bufnr = 0;
|
|
this.currIndex = 0;
|
|
this.highlights = [];
|
|
this.items = [];
|
|
this.disposables = [];
|
|
this.selected = new Set();
|
|
this.creating = false;
|
|
this._onDidChangeLine = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidOpen = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidClose = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidChange = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDidLineChange = new vscode_languageserver_protocol_1.Emitter();
|
|
this._onDoubleClick = new vscode_languageserver_protocol_1.Emitter();
|
|
this.onDidChangeLine = this._onDidChangeLine.event;
|
|
this.onDidLineChange = this._onDidLineChange.event;
|
|
this.onDidOpen = this._onDidOpen.event;
|
|
this.onDidClose = this._onDidClose.event;
|
|
this.onDidChange = this._onDidChange.event;
|
|
this.onDidDoubleClick = this._onDoubleClick.event;
|
|
let signText = config.get('selectedSignText', '*');
|
|
nvim.command(`sign define CocSelected text=${signText} texthl=CocSelectedText linehl=CocSelectedLine`, true);
|
|
this.signOffset = config.get('signOffset');
|
|
events_1.default.on('BufUnload', async (bufnr) => {
|
|
if (bufnr == this.bufnr) {
|
|
this._bufnr = 0;
|
|
this.window = null;
|
|
this._onDidClose.fire(bufnr);
|
|
}
|
|
}, null, this.disposables);
|
|
let timer;
|
|
events_1.default.on('CursorMoved', async (bufnr, cursor) => {
|
|
if (timer)
|
|
clearTimeout(timer);
|
|
if (bufnr != this.bufnr)
|
|
return;
|
|
let lnum = cursor[0];
|
|
if (this.currIndex + 1 != lnum) {
|
|
this.currIndex = lnum - 1;
|
|
this._onDidChangeLine.fire(lnum);
|
|
}
|
|
}, null, this.disposables);
|
|
events_1.default.on('CursorMoved', debounce(async (bufnr) => {
|
|
if (bufnr != this.bufnr)
|
|
return;
|
|
let [start, end] = await nvim.eval('[line("w0"),line("w$")]');
|
|
if (end < 500)
|
|
return;
|
|
nvim.pauseNotification();
|
|
this.doHighlight(start - 1, end);
|
|
nvim.command('redraw', true);
|
|
await nvim.resumeNotification(false, true);
|
|
}, 100));
|
|
}
|
|
set index(n) {
|
|
if (n < 0 || n >= this.items.length)
|
|
return;
|
|
this.currIndex = n;
|
|
if (this.window) {
|
|
let { nvim } = this;
|
|
nvim.pauseNotification();
|
|
this.setCursor(n + 1, 0);
|
|
nvim.command('redraw', true);
|
|
nvim.resumeNotification(false, true).logError();
|
|
}
|
|
}
|
|
get index() {
|
|
return this.currIndex;
|
|
}
|
|
getItem(delta) {
|
|
let { currIndex } = this;
|
|
return this.items[currIndex + delta];
|
|
}
|
|
get item() {
|
|
let { window } = this;
|
|
if (!window)
|
|
return Promise.resolve(null);
|
|
return window.cursor.then(cursor => {
|
|
this.currIndex = cursor[0] - 1;
|
|
return this.items[this.currIndex];
|
|
}, _e => {
|
|
return null;
|
|
});
|
|
}
|
|
async echoMessage(item) {
|
|
if (this.bufnr)
|
|
return;
|
|
let { items } = this;
|
|
let idx = items.indexOf(item);
|
|
let msg = `[${idx + 1}/${items.length}] ${item.label || ''}`;
|
|
this.nvim.callTimer('coc#util#echo_lines', [[msg]], true);
|
|
}
|
|
async updateItem(item, index) {
|
|
if (!this.bufnr || workspace_1.default.bufnr != this.bufnr)
|
|
return;
|
|
let obj = Object.assign({ resolved: true }, item);
|
|
if (index < this.length) {
|
|
this.items[index] = obj;
|
|
let { nvim } = this;
|
|
nvim.pauseNotification();
|
|
nvim.command('setl modifiable', true);
|
|
nvim.call('setline', [index + 1, obj.label], true);
|
|
nvim.command('setl nomodifiable', true);
|
|
await nvim.resumeNotification();
|
|
}
|
|
}
|
|
async getItems() {
|
|
if (this.length == 0)
|
|
return [];
|
|
let mode = await this.nvim.call('mode');
|
|
if (mode == 'v' || mode == 'V') {
|
|
let [start, end] = await this.getSelectedRange();
|
|
let res = [];
|
|
for (let i = start; i <= end; i++) {
|
|
res.push(this.items[i - 1]);
|
|
}
|
|
return res;
|
|
}
|
|
let { selectedItems } = this;
|
|
if (selectedItems.length)
|
|
return selectedItems;
|
|
let item = await this.item;
|
|
return item == null ? [] : [item];
|
|
}
|
|
async onMouse(event) {
|
|
let { nvim, window } = this;
|
|
let winid = await nvim.getVvar('mouse_winid');
|
|
if (!window)
|
|
return;
|
|
let lnum = await nvim.getVvar('mouse_lnum');
|
|
let col = await nvim.getVvar('mouse_col');
|
|
if (event == 'mouseDown') {
|
|
this.mouseDown = { winid, lnum, col, current: winid == window.id };
|
|
return;
|
|
}
|
|
let current = winid == window.id;
|
|
if (current && event == 'doubleClick') {
|
|
this.setCursor(lnum, 0);
|
|
this._onDoubleClick.fire();
|
|
}
|
|
if (!this.mouseDown || this.mouseDown.winid != this.mouseDown.winid)
|
|
return;
|
|
if (current && event == 'mouseDrag') {
|
|
await this.selectLines(this.mouseDown.lnum, lnum);
|
|
}
|
|
else if (current && event == 'mouseUp') {
|
|
if (this.mouseDown.lnum == lnum) {
|
|
nvim.pauseNotification();
|
|
this.clearSelection();
|
|
this.setCursor(lnum, 0);
|
|
nvim.command('redraw', true);
|
|
await nvim.resumeNotification();
|
|
}
|
|
else {
|
|
await this.selectLines(this.mouseDown.lnum, lnum);
|
|
}
|
|
}
|
|
else if (!current && event == 'mouseUp') {
|
|
nvim.pauseNotification();
|
|
nvim.call('win_gotoid', winid, true);
|
|
nvim.call('cursor', [lnum, col], true);
|
|
await nvim.resumeNotification();
|
|
}
|
|
}
|
|
reset() {
|
|
this.items = [];
|
|
this.mouseDown = null;
|
|
this.selected = new Set();
|
|
this._bufnr = 0;
|
|
this.window = null;
|
|
}
|
|
hide() {
|
|
let { bufnr, window, nvim } = this;
|
|
if (window) {
|
|
nvim.call('coc#util#close', [window.id], true);
|
|
}
|
|
if (bufnr) {
|
|
nvim.command(`silent! bd! ${bufnr}`, true);
|
|
}
|
|
}
|
|
async resume(name, listOptions) {
|
|
let { items, selected, nvim, signOffset } = this;
|
|
await this.drawItems(items, name, listOptions, true);
|
|
if (selected.size > 0 && this.bufnr) {
|
|
nvim.pauseNotification();
|
|
for (let lnum of selected) {
|
|
nvim.command(`sign place ${signOffset + lnum} line=${lnum} name=CocSelected buffer=${this.bufnr}`, true);
|
|
}
|
|
await nvim.resumeNotification();
|
|
}
|
|
}
|
|
async toggleSelection() {
|
|
let { nvim, selected, signOffset, bufnr } = this;
|
|
if (workspace_1.default.bufnr != bufnr)
|
|
return;
|
|
let lnum = await nvim.call('line', '.');
|
|
let mode = await nvim.call('mode');
|
|
if (mode == 'v' || mode == 'V') {
|
|
let [start, end] = await this.getSelectedRange();
|
|
let exists = selected.has(start);
|
|
let reverse = start > end;
|
|
if (reverse)
|
|
[start, end] = [end, start];
|
|
for (let i = start; i <= end; i++) {
|
|
if (!exists) {
|
|
selected.add(i);
|
|
nvim.command(`sign place ${signOffset + i} line=${i} name=CocSelected buffer=${bufnr}`, true);
|
|
}
|
|
else {
|
|
selected.delete(i);
|
|
nvim.command(`sign unplace ${signOffset + i} buffer=${bufnr}`, true);
|
|
}
|
|
}
|
|
this.setCursor(end, 0);
|
|
nvim.command('redraw', true);
|
|
await nvim.resumeNotification();
|
|
return;
|
|
}
|
|
let exists = selected.has(lnum);
|
|
nvim.pauseNotification();
|
|
if (exists) {
|
|
selected.delete(lnum);
|
|
nvim.command(`sign unplace ${signOffset + lnum} buffer=${bufnr}`, true);
|
|
}
|
|
else {
|
|
selected.add(lnum);
|
|
nvim.command(`sign place ${signOffset + lnum} line=${lnum} name=CocSelected buffer=${bufnr}`, true);
|
|
}
|
|
this.setCursor(lnum + 1, 0);
|
|
nvim.command('redraw', true);
|
|
await nvim.resumeNotification();
|
|
}
|
|
async selectLines(start, end) {
|
|
let { nvim, signOffset, bufnr, length } = this;
|
|
this.clearSelection();
|
|
let { selected } = this;
|
|
nvim.pauseNotification();
|
|
let reverse = start > end;
|
|
if (reverse)
|
|
[start, end] = [end, start];
|
|
for (let i = start; i <= end; i++) {
|
|
if (i > length)
|
|
break;
|
|
selected.add(i);
|
|
nvim.command(`sign place ${signOffset + i} line=${i} name=CocSelected buffer=${bufnr}`, true);
|
|
}
|
|
this.setCursor(end, 0);
|
|
nvim.command('redraw', true);
|
|
await nvim.resumeNotification();
|
|
}
|
|
async selectAll() {
|
|
let { length } = this;
|
|
if (length == 0)
|
|
return;
|
|
await this.selectLines(1, length);
|
|
}
|
|
clearSelection() {
|
|
let { selected, nvim, signOffset, bufnr } = this;
|
|
if (!bufnr)
|
|
return;
|
|
if (selected.size > 0) {
|
|
let signIds = [];
|
|
for (let lnum of selected) {
|
|
signIds.push(signOffset + lnum);
|
|
}
|
|
nvim.call('coc#util#unplace_signs', [bufnr, signIds], true);
|
|
this.selected = new Set();
|
|
}
|
|
}
|
|
get shown() {
|
|
return this._bufnr != 0;
|
|
}
|
|
get bufnr() {
|
|
return this._bufnr;
|
|
}
|
|
get ready() {
|
|
if (this._bufnr)
|
|
return Promise.resolve();
|
|
if (this.creating) {
|
|
return new Promise(resolve => {
|
|
let disposable = this.onDidOpen(() => {
|
|
disposable.dispose();
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
async drawItems(items, name, listOptions, reload = false) {
|
|
let { bufnr, config, nvim } = this;
|
|
this.newTab = listOptions.position == 'tab';
|
|
let maxHeight = config.get('maxHeight', 12);
|
|
let height = Math.max(1, Math.min(items.length, maxHeight));
|
|
let limitLines = config.get('limitLines', 30000);
|
|
let curr = this.items[this.index];
|
|
this.items = items.slice(0, limitLines);
|
|
if (bufnr == 0 && !this.creating) {
|
|
this.creating = true;
|
|
let [bufnr, winid] = await nvim.call('coc#list#create', [listOptions.position, height, name, listOptions.numberSelect]);
|
|
this._bufnr = bufnr;
|
|
this.window = nvim.createWindow(winid);
|
|
this.height = height;
|
|
this._onDidOpen.fire(this.bufnr);
|
|
this.creating = false;
|
|
}
|
|
else {
|
|
await this.ready;
|
|
}
|
|
let lines = this.items.map(item => item.label);
|
|
this.clearSelection();
|
|
await this.setLines(lines, false, reload ? this.currIndex : 0);
|
|
let item = this.items[this.index] || { label: '' };
|
|
if (!curr || curr.label != item.label) {
|
|
this._onDidLineChange.fire(this.index + 1);
|
|
}
|
|
}
|
|
async appendItems(items) {
|
|
let { config } = this;
|
|
let limitLines = config.get('limitLines', 1000);
|
|
let curr = this.items.length;
|
|
if (curr >= limitLines) {
|
|
this._onDidChange.fire();
|
|
return;
|
|
}
|
|
let max = limitLines - curr;
|
|
let append = items.slice(0, max);
|
|
this.items = this.items.concat(append);
|
|
if (this.creating)
|
|
return;
|
|
await this.setLines(append.map(item => item.label), curr > 0, this.currIndex);
|
|
}
|
|
async setLines(lines, append = false, index) {
|
|
let { nvim, bufnr, window, config } = this;
|
|
if (!bufnr || !window)
|
|
return;
|
|
let resize = !this.newTab && config.get('autoResize', true);
|
|
let buf = nvim.createBuffer(bufnr);
|
|
nvim.pauseNotification();
|
|
nvim.call('win_gotoid', window.id, true);
|
|
if (!append) {
|
|
nvim.call('clearmatches', [], true);
|
|
}
|
|
if (resize) {
|
|
let maxHeight = config.get('maxHeight', 12);
|
|
let height = Math.max(1, Math.min(this.items.length, maxHeight));
|
|
this.height = height;
|
|
nvim.call('coc#list#set_height', [height], true);
|
|
}
|
|
if (!append) {
|
|
if (!lines.length) {
|
|
lines = ['Press ? on normal mode to get help.'];
|
|
nvim.call('matchaddpos', ['Comment', [[1]], 99], true);
|
|
}
|
|
}
|
|
nvim.command('setl modifiable', true);
|
|
if (workspace_1.default.isVim) {
|
|
nvim.call('coc#list#setlines', [lines, append], true);
|
|
}
|
|
else {
|
|
buf.setLines(lines, { start: append ? -1 : 0, end: -1, strictIndexing: false }, true);
|
|
}
|
|
nvim.command('setl nomodifiable', true);
|
|
if (!append && index == 0) {
|
|
this.doHighlight(0, 300);
|
|
}
|
|
else {
|
|
let height = this.newTab ? workspace_1.default.env.lines : this.height;
|
|
this.doHighlight(Math.max(0, index - height), Math.min(index + height + 1, this.length - 1));
|
|
}
|
|
if (!append)
|
|
window.notify('nvim_win_set_cursor', [[index + 1, 0]]);
|
|
this._onDidChange.fire();
|
|
if (workspace_1.default.isVim)
|
|
nvim.command('redraw', true);
|
|
let [, err] = await nvim.resumeNotification();
|
|
if (err)
|
|
logger.error(err);
|
|
}
|
|
restoreWindow() {
|
|
if (this.newTab)
|
|
return;
|
|
let { window, height } = this;
|
|
if (window && height) {
|
|
this.nvim.call('coc#list#restore', [window.id, height], true);
|
|
}
|
|
}
|
|
dispose() {
|
|
util_1.disposeAll(this.disposables);
|
|
}
|
|
get length() {
|
|
return this.items.length;
|
|
}
|
|
get selectedItems() {
|
|
let { selected, items } = this;
|
|
let res = [];
|
|
for (let i of selected) {
|
|
if (items[i - 1])
|
|
res.push(items[i - 1]);
|
|
}
|
|
return res;
|
|
}
|
|
doHighlight(start, end) {
|
|
let { nvim } = workspace_1.default;
|
|
let { highlights, items } = this;
|
|
for (let i = start; i <= Math.min(end, items.length - 1); i++) {
|
|
let { ansiHighlights } = items[i];
|
|
let highlight = highlights[i];
|
|
if (ansiHighlights) {
|
|
for (let hi of ansiHighlights) {
|
|
let { span, hlGroup } = hi;
|
|
nvim.call('matchaddpos', [hlGroup, [[i + 1, span[0] + 1, span[1] - span[0]]], 9], true);
|
|
}
|
|
}
|
|
if (highlight) {
|
|
let { spans, hlGroup } = highlight;
|
|
for (let span of spans) {
|
|
nvim.call('matchaddpos', [hlGroup || 'Search', [[i + 1, span[0] + 1, span[1] - span[0]]], 11], true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
setCursor(lnum, col) {
|
|
let { window, bufnr, items } = this;
|
|
let max = items.length == 0 ? 1 : items.length;
|
|
if (!bufnr || !window || lnum > max)
|
|
return;
|
|
window.notify('nvim_win_set_cursor', [[lnum, col]]);
|
|
if (this.currIndex + 1 != lnum) {
|
|
this.currIndex = lnum - 1;
|
|
this._onDidChangeLine.fire(lnum);
|
|
}
|
|
}
|
|
addHighlights(highlights, append = false) {
|
|
let limitLines = this.config.get('limitLines', 1000);
|
|
if (!append) {
|
|
this.highlights = highlights.slice(0, limitLines);
|
|
}
|
|
else {
|
|
if (this.highlights.length < limitLines) {
|
|
this.highlights = this.highlights.concat(highlights.slice(0, limitLines - this.highlights.length));
|
|
}
|
|
}
|
|
}
|
|
async getSelectedRange() {
|
|
let { nvim } = this;
|
|
await nvim.call('coc#list#stop_prompt');
|
|
await nvim.eval('feedkeys("\\<esc>", "in")');
|
|
let [, start] = await nvim.call('getpos', "'<");
|
|
let [, end] = await nvim.call('getpos', "'>");
|
|
if (start > end) {
|
|
[start, end] = [end, start];
|
|
}
|
|
let method = workspace_1.default.isVim ? 'coc#list#prompt_start' : 'coc#list#start_prompt';
|
|
this.nvim.call(method, [], true);
|
|
return [start, end];
|
|
}
|
|
}
|
|
exports.default = ListUI;
|
|
//# sourceMappingURL=ui.js.map
|
|
|
|
/***/ }),
|
|
/* 387 */
|
|
/***/ (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__(149);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const ansiparse_1 = __webpack_require__(350);
|
|
const diff_1 = __webpack_require__(208);
|
|
const fzy_1 = __webpack_require__(384);
|
|
const score_1 = __webpack_require__(388);
|
|
const string_1 = __webpack_require__(210);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
const logger = __webpack_require__(186)('list-worker');
|
|
const controlCode = '\x1b';
|
|
// perform loading task
|
|
class Worker {
|
|
constructor(nvim, manager) {
|
|
this.nvim = nvim;
|
|
this.manager = manager;
|
|
this.recentFiles = [];
|
|
this._loading = false;
|
|
this.totalItems = [];
|
|
this._onDidChangeItems = new vscode_languageserver_protocol_1.Emitter();
|
|
this.onDidChangeItems = this._onDidChangeItems.event;
|
|
let { prompt } = manager;
|
|
prompt.onDidChangeInput(async () => {
|
|
let { listOptions } = manager;
|
|
let { interactive } = listOptions;
|
|
let time = manager.getConfig('interactiveDebounceTime', 100);
|
|
if (this.timer)
|
|
clearTimeout(this.timer);
|
|
// reload or filter items
|
|
if (interactive) {
|
|
this.stop();
|
|
this.timer = setTimeout(async () => {
|
|
await this.loadItems();
|
|
}, time);
|
|
}
|
|
else if (this.length) {
|
|
let wait = Math.max(Math.min(Math.floor(this.length / 200), 300), 50);
|
|
this.timer = setTimeout(async () => {
|
|
await this.drawItems();
|
|
}, wait);
|
|
}
|
|
});
|
|
}
|
|
loadMru() {
|
|
let mru = workspace_1.default.createMru('mru');
|
|
mru.load().then(files => {
|
|
this.recentFiles = files;
|
|
}).logError();
|
|
}
|
|
set loading(loading) {
|
|
if (this._loading == loading)
|
|
return;
|
|
this._loading = loading;
|
|
let { nvim } = this;
|
|
if (loading) {
|
|
this.interval = setInterval(async () => {
|
|
let idx = Math.floor((new Date()).getMilliseconds() / 100);
|
|
nvim.pauseNotification();
|
|
nvim.setVar('coc_list_loading_status', frames[idx], true);
|
|
nvim.command('redraws', true);
|
|
nvim.resumeNotification(false, true).logError();
|
|
}, 100);
|
|
}
|
|
else {
|
|
if (this.interval) {
|
|
clearInterval(this.interval);
|
|
nvim.pauseNotification();
|
|
nvim.setVar('coc_list_loading_status', '', true);
|
|
nvim.command('redraws', true);
|
|
nvim.resumeNotification(false, true).logError();
|
|
}
|
|
}
|
|
}
|
|
get isLoading() {
|
|
return this._loading;
|
|
}
|
|
async loadItems(reload = false) {
|
|
let { context, list, listOptions } = this.manager;
|
|
if (!list)
|
|
return;
|
|
this.loadMru();
|
|
if (this.timer)
|
|
clearTimeout(this.timer);
|
|
this.loading = true;
|
|
let { interactive } = listOptions;
|
|
let source = this.tokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource();
|
|
let token = source.token;
|
|
let items = await list.loadItems(context, token);
|
|
if (token.isCancellationRequested)
|
|
return;
|
|
if (!items || Array.isArray(items)) {
|
|
items = (items || []);
|
|
this.totalItems = items.map(item => {
|
|
item.label = this.fixLabel(item.label);
|
|
this.parseListItemAnsi(item);
|
|
return item;
|
|
});
|
|
this.loading = false;
|
|
let highlights = [];
|
|
if (!interactive) {
|
|
let res = this.filterItems(items);
|
|
items = res.items;
|
|
highlights = res.highlights;
|
|
}
|
|
else {
|
|
highlights = this.getItemsHighlight(items);
|
|
}
|
|
this._onDidChangeItems.fire({
|
|
items,
|
|
highlights,
|
|
reload
|
|
});
|
|
}
|
|
else {
|
|
let task = items;
|
|
let totalItems = this.totalItems = [];
|
|
let count = 0;
|
|
let currInput = context.input;
|
|
let timer;
|
|
let lastTs;
|
|
let _onData = () => {
|
|
lastTs = Date.now();
|
|
if (token.isCancellationRequested || !this.manager.isActivated)
|
|
return;
|
|
if (count >= totalItems.length)
|
|
return;
|
|
let inputChanged = this.input != currInput;
|
|
if (interactive && inputChanged)
|
|
return;
|
|
if (count == 0 || inputChanged) {
|
|
currInput = this.input;
|
|
count = totalItems.length;
|
|
let items;
|
|
let highlights = [];
|
|
if (interactive) {
|
|
items = totalItems.slice();
|
|
highlights = this.getItemsHighlight(items);
|
|
}
|
|
else {
|
|
let res = this.filterItems(totalItems);
|
|
items = res.items;
|
|
highlights = res.highlights;
|
|
}
|
|
this._onDidChangeItems.fire({ items, highlights, reload, append: false });
|
|
}
|
|
else {
|
|
let remain = totalItems.slice(count);
|
|
count = totalItems.length;
|
|
let items;
|
|
let highlights = [];
|
|
if (!interactive) {
|
|
let res = this.filterItems(remain);
|
|
items = res.items;
|
|
highlights = res.highlights;
|
|
}
|
|
else {
|
|
items = remain;
|
|
highlights = this.getItemsHighlight(remain);
|
|
}
|
|
this._onDidChangeItems.fire({ items, highlights, append: true });
|
|
}
|
|
};
|
|
task.on('data', async (item) => {
|
|
if (timer)
|
|
clearTimeout(timer);
|
|
if (token.isCancellationRequested)
|
|
return;
|
|
if (interactive && this.input != currInput)
|
|
return;
|
|
item.label = this.fixLabel(item.label);
|
|
this.parseListItemAnsi(item);
|
|
totalItems.push(item);
|
|
if (this.input != currInput)
|
|
return;
|
|
if ((!lastTs && totalItems.length == 500)
|
|
|| Date.now() - lastTs > 200) {
|
|
_onData();
|
|
}
|
|
else {
|
|
timer = setTimeout(_onData, 50);
|
|
}
|
|
});
|
|
let disposable = token.onCancellationRequested(() => {
|
|
this.loading = false;
|
|
disposable.dispose();
|
|
if (timer)
|
|
clearTimeout(timer);
|
|
if (task) {
|
|
task.dispose();
|
|
task = null;
|
|
}
|
|
});
|
|
task.on('error', async (error) => {
|
|
task = null;
|
|
this.loading = false;
|
|
disposable.dispose();
|
|
if (timer)
|
|
clearTimeout(timer);
|
|
await this.manager.cancel();
|
|
workspace_1.default.showMessage(`Task error: ${error.toString()}`, 'error');
|
|
logger.error(error);
|
|
});
|
|
task.on('end', async () => {
|
|
task = null;
|
|
this.loading = false;
|
|
disposable.dispose();
|
|
if (timer)
|
|
clearTimeout(timer);
|
|
if (token.isCancellationRequested)
|
|
return;
|
|
if (totalItems.length == 0) {
|
|
this._onDidChangeItems.fire({ items: [], highlights: [] });
|
|
}
|
|
else {
|
|
_onData();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
// draw all items with filter if necessary
|
|
async drawItems() {
|
|
let { totalItems } = this;
|
|
let { listOptions, isActivated } = this.manager;
|
|
if (!isActivated)
|
|
return;
|
|
let { interactive } = listOptions;
|
|
let items = totalItems;
|
|
let highlights = [];
|
|
if (!interactive) {
|
|
let res = this.filterItems(totalItems);
|
|
items = res.items;
|
|
highlights = res.highlights;
|
|
}
|
|
else {
|
|
highlights = this.getItemsHighlight(items);
|
|
}
|
|
this._onDidChangeItems.fire({ items, highlights });
|
|
}
|
|
stop() {
|
|
if (this.tokenSource) {
|
|
this.tokenSource.cancel();
|
|
this.tokenSource = null;
|
|
}
|
|
this.loading = false;
|
|
if (this.timer) {
|
|
clearTimeout(this.timer);
|
|
}
|
|
}
|
|
get length() {
|
|
return this.totalItems.length;
|
|
}
|
|
get input() {
|
|
return this.manager.prompt.input;
|
|
}
|
|
getItemsHighlight(items) {
|
|
let { input } = this;
|
|
if (!input)
|
|
return [];
|
|
return items.map(item => {
|
|
let filterLabel = getFilterLabel(item);
|
|
if (filterLabel == '')
|
|
return null;
|
|
let res = score_1.getMatchResult(filterLabel, input);
|
|
if (!res || !res.score)
|
|
return null;
|
|
return this.getHighlights(filterLabel, res.matches);
|
|
});
|
|
}
|
|
filterItems(items) {
|
|
let { input } = this.manager.prompt;
|
|
let highlights = [];
|
|
let { sort, matcher, ignorecase } = this.manager.listOptions;
|
|
if (input.length == 0) {
|
|
let filtered = items.slice();
|
|
let sort = filtered.length && typeof filtered[0].recentScore == 'number';
|
|
return {
|
|
items: sort ? filtered.sort((a, b) => b.recentScore - a.recentScore) : filtered,
|
|
highlights
|
|
};
|
|
}
|
|
let extended = this.manager.getConfig('extendedSearchMode', true);
|
|
let filtered;
|
|
if (input.length > 0) {
|
|
let inputs = extended ? input.split(/\s+/) : [input];
|
|
if (matcher == 'strict') {
|
|
filtered = items.filter(item => {
|
|
let spans = [];
|
|
let filterLabel = getFilterLabel(item);
|
|
for (let input of inputs) {
|
|
let idx = ignorecase ? filterLabel.toLowerCase().indexOf(input.toLowerCase()) : filterLabel.indexOf(input);
|
|
if (idx == -1)
|
|
return false;
|
|
spans.push([string_1.byteIndex(filterLabel, idx), string_1.byteIndex(filterLabel, idx + string_1.byteLength(input))]);
|
|
}
|
|
highlights.push({ spans });
|
|
return true;
|
|
});
|
|
}
|
|
else if (matcher == 'regex') {
|
|
let flags = ignorecase ? 'iu' : 'u';
|
|
let regexes = inputs.reduce((p, c) => {
|
|
try {
|
|
let regex = new RegExp(c, flags);
|
|
p.push(regex);
|
|
// tslint:disable-next-line: no-empty
|
|
}
|
|
catch (e) { }
|
|
return p;
|
|
}, []);
|
|
filtered = items.filter(item => {
|
|
let spans = [];
|
|
let filterLabel = getFilterLabel(item);
|
|
for (let regex of regexes) {
|
|
let ms = filterLabel.match(regex);
|
|
if (ms == null)
|
|
return false;
|
|
spans.push([string_1.byteIndex(filterLabel, ms.index), string_1.byteIndex(filterLabel, ms.index + string_1.byteLength(ms[0]))]);
|
|
}
|
|
highlights.push({ spans });
|
|
return true;
|
|
});
|
|
}
|
|
else {
|
|
filtered = items.filter(item => {
|
|
let filterText = item.filterText || item.label;
|
|
return inputs.every(s => fzy_1.hasMatch(s, filterText));
|
|
});
|
|
filtered = filtered.map(item => {
|
|
let filterLabel = getFilterLabel(item);
|
|
let matchScore = 0;
|
|
let matches = [];
|
|
for (let input of inputs) {
|
|
matches.push(...fzy_1.positions(input, filterLabel));
|
|
matchScore += fzy_1.score(input, filterLabel);
|
|
}
|
|
let { recentScore } = item;
|
|
if (!recentScore && item.location) {
|
|
let uri = getItemUri(item);
|
|
if (uri.startsWith('file')) {
|
|
let fsPath = vscode_uri_1.URI.parse(uri).fsPath;
|
|
recentScore = -this.recentFiles.indexOf(fsPath);
|
|
}
|
|
}
|
|
return Object.assign({}, item, {
|
|
filterLabel,
|
|
score: matchScore,
|
|
recentScore,
|
|
matches
|
|
});
|
|
});
|
|
if (sort && items.length) {
|
|
filtered.sort((a, b) => {
|
|
if (a.score != b.score)
|
|
return b.score - a.score;
|
|
if (input.length && a.recentScore != b.recentScore) {
|
|
return (a.recentScore || -Infinity) - (b.recentScore || -Infinity);
|
|
}
|
|
if (a.location && b.location) {
|
|
let au = getItemUri(a);
|
|
let bu = getItemUri(b);
|
|
return au > bu ? 1 : -1;
|
|
}
|
|
return a.label > b.label ? 1 : -1;
|
|
});
|
|
}
|
|
for (let item of filtered) {
|
|
if (!item.matches)
|
|
continue;
|
|
let hi = this.getHighlights(item.filterLabel, item.matches);
|
|
highlights.push(hi);
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
items: filtered,
|
|
highlights
|
|
};
|
|
}
|
|
getHighlights(text, matches) {
|
|
let spans = [];
|
|
if (matches.length) {
|
|
let start = matches.shift();
|
|
let next = matches.shift();
|
|
let curr = start;
|
|
while (next) {
|
|
if (next == curr + 1) {
|
|
curr = next;
|
|
next = matches.shift();
|
|
continue;
|
|
}
|
|
spans.push([string_1.byteIndex(text, start), string_1.byteIndex(text, curr) + 1]);
|
|
start = next;
|
|
curr = start;
|
|
next = matches.shift();
|
|
}
|
|
spans.push([string_1.byteIndex(text, start), string_1.byteIndex(text, curr) + 1]);
|
|
}
|
|
return { spans };
|
|
}
|
|
// set correct label, add ansi highlights
|
|
parseListItemAnsi(item) {
|
|
let { label } = item;
|
|
if (item.ansiHighlights || label.indexOf(controlCode) == -1)
|
|
return;
|
|
let { line, highlights } = ansiparse_1.parseAnsiHighlights(label);
|
|
item.label = line;
|
|
item.ansiHighlights = highlights;
|
|
}
|
|
fixLabel(label) {
|
|
let { columns } = workspace_1.default.env;
|
|
label = label.split('\n').join(' ');
|
|
return label.slice(0, columns * 2);
|
|
}
|
|
}
|
|
exports.default = Worker;
|
|
function getFilterLabel(item) {
|
|
return item.filterText != null ? diff_1.patchLine(item.filterText, item.label) : item.label;
|
|
}
|
|
function getItemUri(item) {
|
|
let { location } = item;
|
|
if (typeof location == 'string')
|
|
return location;
|
|
return location.uri;
|
|
}
|
|
//# sourceMappingURL=worker.js.map
|
|
|
|
/***/ }),
|
|
/* 388 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const path_1 = __webpack_require__(57);
|
|
const fuzzy_1 = __webpack_require__(367);
|
|
// 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
|
|
function getMatchResult(text, query, filename = '') {
|
|
if (!query)
|
|
return { score: 1 };
|
|
let matches = [];
|
|
let codes = fuzzy_1.getCharCodes(query);
|
|
let filenameIdx = filename ? text.indexOf(filename) : -1;
|
|
let matchBase = filenameIdx != -1 && fuzzy_1.fuzzyMatch(codes, filename);
|
|
let score = 0;
|
|
let c = query[0];
|
|
let idx = 0;
|
|
// base => start => pathSeparator => fuzzy
|
|
if (matchBase) {
|
|
if (filename.startsWith(c)) {
|
|
score = score + 2;
|
|
idx = filenameIdx + 1;
|
|
matches.push(filenameIdx);
|
|
}
|
|
else if (filename[0].toLowerCase() == c) {
|
|
score = score + 1.5;
|
|
idx = filenameIdx + 1;
|
|
matches.push(filenameIdx);
|
|
}
|
|
else {
|
|
for (let i = 1; i < filename.length; i++) {
|
|
if (fuzzy_1.fuzzyChar(c, filename[i])) {
|
|
score = score + 1;
|
|
idx = filenameIdx + i + 1;
|
|
matches.push(filenameIdx + i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (text.startsWith(c)) {
|
|
score = score + 1;
|
|
matches.push(0);
|
|
idx = 1;
|
|
}
|
|
else {
|
|
for (let i = 1; i < text.length; i++) {
|
|
let pre = text[i - 1];
|
|
if (pre == path_1.sep && text[i] == c) {
|
|
score = score + 1;
|
|
matches.push(i);
|
|
idx = i + 1;
|
|
break;
|
|
}
|
|
}
|
|
if (idx == 0) {
|
|
for (let i = 0; i < text.length; i++) {
|
|
if (fuzzy_1.fuzzyChar(c, text[i])) {
|
|
score = score + 0.5;
|
|
matches.push(i);
|
|
idx = i + 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (idx == 0)
|
|
return { score: 0 };
|
|
if (codes.length == 1)
|
|
return { score, matches };
|
|
return nextResult(codes.slice(1), text, idx, { score, matches });
|
|
}
|
|
exports.getMatchResult = getMatchResult;
|
|
/**
|
|
*
|
|
* @public
|
|
* @param {number[]} codes - remain codes
|
|
* @param {string} text - total text
|
|
* @param {number} idx - start index of text
|
|
* @param {MatchResult} curr - current result
|
|
* @returns {MatchResult | null}
|
|
*/
|
|
function nextResult(codes, text, idx, curr) {
|
|
let { score, matches } = curr;
|
|
let results = [];
|
|
let c = codes[0];
|
|
let remain = codes.slice(1);
|
|
let result;
|
|
function getRemianResult(index) {
|
|
if (!result)
|
|
return;
|
|
if (remain.length == 0) {
|
|
results.push(result);
|
|
}
|
|
else if (result) {
|
|
let res = nextResult(remain, text, index, result);
|
|
if (res)
|
|
results.push(res);
|
|
}
|
|
}
|
|
let followed = idx < text.length ? text[idx].charCodeAt(0) : null;
|
|
if (!followed)
|
|
return null;
|
|
if (followed == c) {
|
|
result = { score: score + 1, matches: matches.concat([idx]) };
|
|
getRemianResult(idx + 1);
|
|
}
|
|
else if (fuzzy_1.caseMatch(c, followed)) {
|
|
result = { score: score + 0.5, matches: matches.concat([idx]) };
|
|
getRemianResult(idx + 1);
|
|
}
|
|
if (idx + 1 < text.length) {
|
|
// follow path
|
|
for (let i = idx + 1; i < text.length; i++) {
|
|
let ch = text[i].charCodeAt(0);
|
|
if (text[i - 1] == path_1.sep && fuzzy_1.caseMatch(c, ch)) {
|
|
let add = c == ch ? 1 : 0.5;
|
|
result = { score: score + add, matches: matches.concat([i]) };
|
|
getRemianResult(i + 1);
|
|
break;
|
|
}
|
|
}
|
|
// next fuzzy
|
|
for (let i = idx + 1; i < text.length; i++) {
|
|
let ch = text[i].charCodeAt(0);
|
|
if (fuzzy_1.caseMatch(c, ch)) {
|
|
let add = c == ch ? 0.5 : 0.2;
|
|
result = { score: score + add, matches: matches.concat([i]) };
|
|
getRemianResult(i + 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return results.length ? bestResult(results) : null;
|
|
}
|
|
function bestResult(results) {
|
|
let res = results[0];
|
|
for (let i = 1; i < results.length; i++) {
|
|
if (results[i].score > res.score) {
|
|
res = results[i];
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
//# sourceMappingURL=score.js.map
|
|
|
|
/***/ }),
|
|
/* 389 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const types_1 = __webpack_require__(189);
|
|
const string_1 = __webpack_require__(210);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('model-source');
|
|
class Source {
|
|
constructor(option) {
|
|
this._disabled = false;
|
|
this.nvim = workspace_1.default.nvim;
|
|
// readonly properties
|
|
this.name = option.name;
|
|
this.filepath = option.filepath || '';
|
|
this.sourceType = option.sourceType || types_1.SourceType.Native;
|
|
this.isSnippet = !!option.isSnippet;
|
|
this.defaults = option;
|
|
}
|
|
/**
|
|
* Priority of source, higher priority makes items lower index.
|
|
*/
|
|
get priority() {
|
|
return this.getConfig('priority', 1);
|
|
}
|
|
/**
|
|
* When triggerOnly is true, not trigger completion on keyword character insert.
|
|
*/
|
|
get triggerOnly() {
|
|
let triggerOnly = this.defaults['triggerOnly'];
|
|
if (typeof triggerOnly == 'boolean')
|
|
return triggerOnly;
|
|
if (!this.triggerCharacters && !this.triggerPatterns)
|
|
return false;
|
|
return Array.isArray(this.triggerPatterns) && this.triggerPatterns.length != 0;
|
|
}
|
|
get triggerCharacters() {
|
|
return this.getConfig('triggerCharacters', null);
|
|
}
|
|
// exists opitonnal function names for remote source
|
|
get optionalFns() {
|
|
return this.defaults['optionalFns'] || [];
|
|
}
|
|
get triggerPatterns() {
|
|
let patterns = this.getConfig('triggerPatterns', null);
|
|
if (!patterns || patterns.length == 0)
|
|
return null;
|
|
return patterns.map(s => {
|
|
return (typeof s === 'string') ? new RegExp(s + '$') : s;
|
|
});
|
|
}
|
|
get shortcut() {
|
|
let shortcut = this.getConfig('shortcut', '');
|
|
return shortcut ? shortcut : this.name.slice(0, 3);
|
|
}
|
|
get enable() {
|
|
if (this._disabled)
|
|
return false;
|
|
return this.getConfig('enable', true);
|
|
}
|
|
get filetypes() {
|
|
return this.getConfig('filetypes', null);
|
|
}
|
|
get disableSyntaxes() {
|
|
return this.getConfig('disableSyntaxes', []);
|
|
}
|
|
getConfig(key, defaultValue) {
|
|
let config = workspace_1.default.getConfiguration(`coc.source.${this.name}`);
|
|
defaultValue = this.defaults.hasOwnProperty(key) ? this.defaults[key] : defaultValue;
|
|
return config.get(key, defaultValue);
|
|
}
|
|
toggle() {
|
|
this._disabled = !this._disabled;
|
|
}
|
|
get firstMatch() {
|
|
return this.getConfig('firstMatch', true);
|
|
}
|
|
get menu() {
|
|
let { shortcut } = this;
|
|
return shortcut ? `[${shortcut}]` : '';
|
|
}
|
|
/**
|
|
* Filter words that too short or doesn't match input
|
|
*/
|
|
filterWords(words, opt) {
|
|
let { firstMatch } = this;
|
|
let res = [];
|
|
let { input } = opt;
|
|
let cword = opt.word;
|
|
if (!input.length)
|
|
return [];
|
|
let cFirst = input[0];
|
|
for (let word of words) {
|
|
if (!word || word.length < 3)
|
|
continue;
|
|
if (firstMatch && cFirst != word[0])
|
|
continue;
|
|
if (!firstMatch && cFirst.toLowerCase() != word[0].toLowerCase())
|
|
continue;
|
|
if (word == cword || word == input)
|
|
continue;
|
|
res.push(word);
|
|
}
|
|
return res;
|
|
}
|
|
/**
|
|
* fix start column for new valid characters
|
|
*
|
|
* @protected
|
|
* @param {CompleteOption} opt
|
|
* @param {string[]} valids - valid charscters
|
|
* @returns {number}
|
|
*/
|
|
fixStartcol(opt, valids) {
|
|
let { col, input, line, bufnr } = opt;
|
|
let start = string_1.byteSlice(line, 0, col);
|
|
let document = workspace_1.default.getDocument(bufnr);
|
|
if (!document)
|
|
return col;
|
|
let { chars } = document;
|
|
for (let i = start.length - 1; i >= 0; i--) {
|
|
let c = start[i];
|
|
if (!chars.isKeywordChar(c) && valids.indexOf(c) === -1) {
|
|
break;
|
|
}
|
|
input = `${c}${input}`;
|
|
col = col - 1;
|
|
}
|
|
opt.col = col;
|
|
opt.input = input;
|
|
return col;
|
|
}
|
|
async shouldComplete(opt) {
|
|
let { disableSyntaxes } = this;
|
|
let synname = opt.synname.toLowerCase();
|
|
if (disableSyntaxes && disableSyntaxes.length && disableSyntaxes.findIndex(s => synname.indexOf(s.toLowerCase()) != -1) !== -1) {
|
|
return false;
|
|
}
|
|
let fn = this.defaults['shouldComplete'];
|
|
if (fn)
|
|
return await Promise.resolve(fn.call(this, opt));
|
|
return true;
|
|
}
|
|
async refresh() {
|
|
let fn = this.defaults['refresh'];
|
|
if (fn)
|
|
await Promise.resolve(fn.call(this));
|
|
}
|
|
async onCompleteDone(item, opt) {
|
|
let fn = this.defaults['onCompleteDone'];
|
|
if (fn)
|
|
await Promise.resolve(fn.call(this, item, opt));
|
|
}
|
|
async doComplete(opt, token) {
|
|
let fn = this.defaults['doComplete'];
|
|
if (fn)
|
|
return await Promise.resolve(fn.call(this, opt, token));
|
|
return null;
|
|
}
|
|
}
|
|
exports.default = Source;
|
|
//# sourceMappingURL=source.js.map
|
|
|
|
/***/ }),
|
|
/* 390 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const fuzzy_1 = __webpack_require__(367);
|
|
const string_1 = __webpack_require__(210);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const source_1 = tslib_1.__importDefault(__webpack_require__(389));
|
|
const logger = __webpack_require__(186)('model-source-vim');
|
|
class VimSource extends source_1.default {
|
|
async callOptinalFunc(fname, args) {
|
|
let exists = this.optionalFns.indexOf(fname) !== -1;
|
|
if (!exists)
|
|
return null;
|
|
let name = `coc#source#${this.name}#${fname}`;
|
|
let res;
|
|
try {
|
|
res = await this.nvim.call(name, args);
|
|
}
|
|
catch (e) {
|
|
workspace_1.default.showMessage(`Vim error from source ${this.name}: ${e.message}`, 'error');
|
|
return null;
|
|
}
|
|
return res;
|
|
}
|
|
async shouldComplete(opt) {
|
|
let shouldRun = await super.shouldComplete(opt);
|
|
if (!shouldRun)
|
|
return false;
|
|
if (this.optionalFns.indexOf('should_complete') === -1)
|
|
return true;
|
|
let res = await this.callOptinalFunc('should_complete', [opt]);
|
|
return !!res;
|
|
}
|
|
async refresh() {
|
|
await this.callOptinalFunc('refresh', []);
|
|
}
|
|
async onCompleteDone(item, opt) {
|
|
await super.onCompleteDone(item, opt);
|
|
if (this.optionalFns.indexOf('on_complete') === -1)
|
|
return;
|
|
this.callOptinalFunc('on_complete', [item]); // tslint:disable-line
|
|
}
|
|
onEnter(bufnr) {
|
|
if (this.optionalFns.indexOf('on_enter') === -1)
|
|
return;
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return;
|
|
let { filetypes } = this;
|
|
if (filetypes && filetypes.indexOf(doc.filetype) == -1)
|
|
return;
|
|
this.callOptinalFunc('on_enter', [{
|
|
bufnr,
|
|
uri: doc.uri,
|
|
languageId: doc.filetype
|
|
}]); // tslint:disable-line
|
|
}
|
|
async doComplete(opt, token) {
|
|
let { col, input, line, colnr } = opt;
|
|
let startcol = await this.callOptinalFunc('get_startcol', [opt]);
|
|
if (token.isCancellationRequested)
|
|
return;
|
|
if (startcol) {
|
|
if (startcol < 0)
|
|
return null;
|
|
startcol = Number(startcol);
|
|
// invalid startcol
|
|
if (isNaN(startcol) || startcol < 0)
|
|
startcol = col;
|
|
if (startcol !== col) {
|
|
input = string_1.byteSlice(line, startcol, colnr - 1);
|
|
opt = Object.assign({}, opt, {
|
|
col: startcol,
|
|
changed: col - startcol,
|
|
input
|
|
});
|
|
}
|
|
}
|
|
let items = await this.nvim.callAsync('coc#util#do_complete', [this.name, opt]);
|
|
if (!items || items.length == 0 || token.isCancellationRequested)
|
|
return null;
|
|
if (this.firstMatch && input.length) {
|
|
let ch = input[0];
|
|
items = items.filter(item => {
|
|
let cfirst = item.filterText ? item.filterText[0] : item.word[0];
|
|
return fuzzy_1.fuzzyChar(ch, cfirst);
|
|
});
|
|
}
|
|
items = items.map(item => {
|
|
if (typeof item == 'string') {
|
|
return { word: item, menu: this.menu, isSnippet: this.isSnippet };
|
|
}
|
|
let menu = item.menu ? item.menu + ' ' : '';
|
|
item.menu = `${menu}${this.menu}`;
|
|
item.isSnippet = this.isSnippet;
|
|
delete item.user_data;
|
|
return item;
|
|
});
|
|
let res = { items };
|
|
if (startcol)
|
|
res.startcol = startcol;
|
|
return res;
|
|
}
|
|
}
|
|
exports.default = VimSource;
|
|
//# sourceMappingURL=source-vim.js.map
|
|
|
|
/***/ }),
|
|
/* 391 */
|
|
/***/ (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__(149);
|
|
const source_1 = tslib_1.__importDefault(__webpack_require__(389));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('source-around');
|
|
class Around extends source_1.default {
|
|
constructor() {
|
|
super({
|
|
name: 'around',
|
|
filepath: __filename
|
|
});
|
|
}
|
|
async doComplete(opt) {
|
|
let { bufnr, input } = opt;
|
|
if (input.length === 0)
|
|
return null;
|
|
let document = workspace_1.default.getDocument(bufnr);
|
|
if (!document)
|
|
return null;
|
|
let words = document.words;
|
|
let moreWords = document.getMoreWords();
|
|
words.push(...moreWords);
|
|
words = this.filterWords(words, opt);
|
|
return {
|
|
items: words.map(word => {
|
|
return {
|
|
word,
|
|
menu: this.menu
|
|
};
|
|
})
|
|
};
|
|
}
|
|
}
|
|
exports.default = Around;
|
|
function regist(sourceMap) {
|
|
sourceMap.set('around', new Around());
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
sourceMap.delete('around');
|
|
});
|
|
}
|
|
exports.regist = regist;
|
|
//# sourceMappingURL=around.js.map
|
|
|
|
/***/ }),
|
|
/* 392 */
|
|
/***/ (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__(149);
|
|
const source_1 = tslib_1.__importDefault(__webpack_require__(389));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('source-buffer');
|
|
class Buffer extends source_1.default {
|
|
constructor() {
|
|
super({
|
|
name: 'buffer',
|
|
filepath: __filename
|
|
});
|
|
}
|
|
get ignoreGitignore() {
|
|
return this.getConfig('ignoreGitignore', true);
|
|
}
|
|
getWords(bufnr) {
|
|
let { ignoreGitignore } = this;
|
|
let words = [];
|
|
workspace_1.default.documents.forEach(document => {
|
|
if (document.bufnr == bufnr)
|
|
return;
|
|
if (ignoreGitignore && document.isIgnored)
|
|
return;
|
|
for (let word of document.words) {
|
|
if (words.indexOf(word) == -1) {
|
|
words.push(word);
|
|
}
|
|
}
|
|
});
|
|
return words;
|
|
}
|
|
async doComplete(opt) {
|
|
let { bufnr, input } = opt;
|
|
if (input.length == 0)
|
|
return null;
|
|
let words = this.getWords(bufnr);
|
|
words = this.filterWords(words, opt);
|
|
return {
|
|
items: words.map(word => {
|
|
return {
|
|
word,
|
|
menu: this.menu
|
|
};
|
|
})
|
|
};
|
|
}
|
|
}
|
|
exports.default = Buffer;
|
|
function regist(sourceMap) {
|
|
sourceMap.set('buffer', new Buffer());
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
sourceMap.delete('buffer');
|
|
});
|
|
}
|
|
exports.regist = regist;
|
|
//# sourceMappingURL=buffer.js.map
|
|
|
|
/***/ }),
|
|
/* 393 */
|
|
/***/ (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__(55));
|
|
const minimatch_1 = tslib_1.__importDefault(__webpack_require__(201));
|
|
const os_1 = tslib_1.__importDefault(__webpack_require__(56));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const util_1 = tslib_1.__importDefault(__webpack_require__(40));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const source_1 = tslib_1.__importDefault(__webpack_require__(389));
|
|
const fs_2 = __webpack_require__(200);
|
|
const string_1 = __webpack_require__(210);
|
|
const logger = __webpack_require__(186)('source-file');
|
|
const pathRe = /(?:\.{0,2}|~|([\w]+)|)\/(?:[\w.@()-]+\/)*(?:[\w.@()-])*$/;
|
|
class File extends source_1.default {
|
|
constructor() {
|
|
super({
|
|
name: 'file',
|
|
filepath: __filename
|
|
});
|
|
}
|
|
getPathOption(opt) {
|
|
let { line, colnr } = opt;
|
|
let part = string_1.byteSlice(line, 0, colnr - 1);
|
|
if (!part || part.slice(-2) == '//')
|
|
return null;
|
|
let ms = part.match(pathRe);
|
|
if (ms && ms.length) {
|
|
let pathstr = ms[0];
|
|
if (pathstr.startsWith('~')) {
|
|
pathstr = os_1.default.homedir() + pathstr.slice(1);
|
|
}
|
|
let input = ms[0].match(/[^/]*$/)[0];
|
|
return { pathstr, part: ms[1], startcol: colnr - input.length - 1, input };
|
|
}
|
|
return null;
|
|
}
|
|
async getFileItem(root, filename) {
|
|
let f = path_1.default.join(root, filename);
|
|
let stat = await fs_2.statAsync(f);
|
|
if (stat) {
|
|
let abbr = stat.isDirectory() ? filename + '/' : filename;
|
|
let word = filename;
|
|
return { word, abbr };
|
|
}
|
|
return null;
|
|
}
|
|
filterFiles(files) {
|
|
let ignoreHidden = this.getConfig('ignoreHidden', true);
|
|
let ignorePatterns = this.getConfig('ignorePatterns', []);
|
|
return files.filter(f => {
|
|
if (f == null)
|
|
return false;
|
|
if (ignoreHidden && /^\./.test(f))
|
|
return false;
|
|
for (let p of ignorePatterns) {
|
|
if (minimatch_1.default(f, p, { dot: true }))
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
}
|
|
async getItemsFromRoot(pathstr, root) {
|
|
let res = [];
|
|
let part = /\/$/.test(pathstr) ? pathstr : path_1.default.dirname(pathstr);
|
|
let dir = path_1.default.isAbsolute(pathstr) ? part : path_1.default.join(root, part);
|
|
let stat = await fs_2.statAsync(dir);
|
|
if (stat && stat.isDirectory()) {
|
|
let files = await util_1.default.promisify(fs_1.default.readdir)(dir);
|
|
files = this.filterFiles(files);
|
|
let items = await Promise.all(files.map(filename => {
|
|
return this.getFileItem(dir, filename);
|
|
}));
|
|
res = res.concat(items);
|
|
}
|
|
res = res.filter(item => item != null);
|
|
return res;
|
|
}
|
|
get trimSameExts() {
|
|
return this.getConfig('trimSameExts', []);
|
|
}
|
|
async doComplete(opt) {
|
|
let { col, filepath } = opt;
|
|
let option = this.getPathOption(opt);
|
|
if (!option)
|
|
return null;
|
|
let { pathstr, part, startcol, input } = option;
|
|
if (startcol < opt.col)
|
|
return null;
|
|
let startPart = opt.col == startcol ? '' : string_1.byteSlice(opt.line, opt.col, startcol);
|
|
let dirname = path_1.default.dirname(filepath);
|
|
let ext = path_1.default.extname(path_1.default.basename(filepath));
|
|
let cwd = await this.nvim.call('getcwd', []);
|
|
let root;
|
|
if (/^\./.test(pathstr)) {
|
|
root = filepath ? path_1.default.dirname(filepath) : cwd;
|
|
}
|
|
else if (/^\//.test(pathstr)) {
|
|
root = /\/$/.test(pathstr) ? pathstr : path_1.default.dirname(pathstr);
|
|
}
|
|
else if (part) {
|
|
if (fs_1.default.existsSync(path_1.default.join(dirname, part))) {
|
|
root = dirname;
|
|
}
|
|
else if (fs_1.default.existsSync(path_1.default.join(cwd, part))) {
|
|
root = cwd;
|
|
}
|
|
}
|
|
else {
|
|
root = cwd;
|
|
}
|
|
if (!root)
|
|
return null;
|
|
let items = await this.getItemsFromRoot(pathstr, root);
|
|
let trimExt = this.trimSameExts.indexOf(ext) != -1;
|
|
let first = input[0];
|
|
if (first && col == startcol)
|
|
items = items.filter(o => o.word[0] === first);
|
|
return {
|
|
items: items.map(item => {
|
|
let ex = path_1.default.extname(item.word);
|
|
item.word = trimExt && ex === ext ? item.word.replace(ext, '') : item.word;
|
|
return {
|
|
word: `${startPart}${item.word}`,
|
|
abbr: `${startPart}${item.abbr}`,
|
|
menu: this.menu
|
|
};
|
|
})
|
|
};
|
|
}
|
|
}
|
|
exports.default = File;
|
|
function regist(sourceMap) {
|
|
sourceMap.set('file', new File());
|
|
return vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
sourceMap.delete('file');
|
|
});
|
|
}
|
|
exports.regist = regist;
|
|
//# sourceMappingURL=file.js.map
|
|
|
|
/***/ }),
|
|
/* 394 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const fuzzy_1 = __webpack_require__(367);
|
|
const string_1 = __webpack_require__(210);
|
|
const match_1 = __webpack_require__(395);
|
|
const logger = __webpack_require__(186)('completion-complete');
|
|
// first time completion
|
|
const FIRST_TIMEOUT = 500;
|
|
class Complete {
|
|
constructor(option, document, recentScores, config, sources, nvim) {
|
|
this.option = option;
|
|
this.document = document;
|
|
this.config = config;
|
|
this.sources = sources;
|
|
this.nvim = nvim;
|
|
// identify this complete
|
|
this.results = [];
|
|
this.completing = new Set();
|
|
this._canceled = false;
|
|
this.tokenSources = new Map();
|
|
this._onDidComplete = new vscode_languageserver_protocol_1.Emitter();
|
|
this.onDidComplete = this._onDidComplete.event;
|
|
Object.defineProperty(this, 'recentScores', {
|
|
get: () => {
|
|
return recentScores || {};
|
|
}
|
|
});
|
|
}
|
|
get isCompleting() {
|
|
return this.completing.size > 0;
|
|
}
|
|
get isCanceled() {
|
|
return this._canceled;
|
|
}
|
|
get isEmpty() {
|
|
return this.results.length == 0;
|
|
}
|
|
get startcol() {
|
|
return this.option.col || 0;
|
|
}
|
|
get input() {
|
|
return this.option.input;
|
|
}
|
|
get isIncomplete() {
|
|
return this.results.findIndex(o => o.isIncomplete == true) !== -1;
|
|
}
|
|
async completeSource(source) {
|
|
let { col } = this.option;
|
|
// new option for each source
|
|
let opt = Object.assign({}, this.option);
|
|
let timeout = this.config.timeout;
|
|
timeout = Math.max(Math.min(timeout, 5000), 1000);
|
|
try {
|
|
if (typeof source.shouldComplete === 'function') {
|
|
let shouldRun = await Promise.resolve(source.shouldComplete(opt));
|
|
if (!shouldRun)
|
|
return null;
|
|
}
|
|
let start = Date.now();
|
|
let oldSource = this.tokenSources.get(source.name);
|
|
if (oldSource)
|
|
oldSource.cancel();
|
|
let tokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource();
|
|
this.tokenSources.set(source.name, tokenSource);
|
|
await new Promise((resolve, reject) => {
|
|
let { name } = source;
|
|
let timer = setTimeout(() => {
|
|
this.nvim.command(`echohl WarningMsg| echom 'source ${source.name} timeout after ${timeout}ms'|echohl None`, true);
|
|
tokenSource.cancel();
|
|
}, timeout);
|
|
let cancelled = false;
|
|
let called = false;
|
|
let empty = false;
|
|
let ft = setTimeout(() => {
|
|
if (called)
|
|
return;
|
|
empty = true;
|
|
resolve();
|
|
}, FIRST_TIMEOUT);
|
|
let onFinished = () => {
|
|
if (called)
|
|
return;
|
|
called = true;
|
|
disposable.dispose();
|
|
clearTimeout(ft);
|
|
clearTimeout(timer);
|
|
this.tokenSources.delete(name);
|
|
};
|
|
let disposable = tokenSource.token.onCancellationRequested(() => {
|
|
disposable.dispose();
|
|
this.completing.delete(name);
|
|
cancelled = true;
|
|
onFinished();
|
|
logger.debug(`Source "${name}" cancelled`);
|
|
resolve();
|
|
});
|
|
this.completing.add(name);
|
|
Promise.resolve(source.doComplete(opt, tokenSource.token)).then(result => {
|
|
this.completing.delete(name);
|
|
if (cancelled)
|
|
return;
|
|
onFinished();
|
|
let dt = Date.now() - start;
|
|
logger.debug(`Source "${name}" takes ${dt}ms`);
|
|
if (result && result.items && result.items.length) {
|
|
result.priority = source.priority;
|
|
result.source = name;
|
|
// lazy completed items
|
|
if (empty && result.startcol && result.startcol != col) {
|
|
this.results = [result];
|
|
}
|
|
else {
|
|
let { results } = this;
|
|
let idx = results.findIndex(o => o.source == name);
|
|
if (idx != -1) {
|
|
results.splice(idx, 1, result);
|
|
}
|
|
else {
|
|
results.push(result);
|
|
}
|
|
}
|
|
if (empty)
|
|
this._onDidComplete.fire();
|
|
resolve();
|
|
}
|
|
else {
|
|
resolve();
|
|
}
|
|
}, err => {
|
|
this.completing.delete(name);
|
|
onFinished();
|
|
reject(err);
|
|
});
|
|
});
|
|
}
|
|
catch (err) {
|
|
this.nvim.command(`echoerr 'Complete ${source.name} error: ${err.message.replace(/'/g, "''")}'`, true);
|
|
logger.error('Complete error:', source.name, err);
|
|
}
|
|
}
|
|
async completeInComplete(resumeInput) {
|
|
let { results, document } = this;
|
|
let remains = results.filter(res => res.isIncomplete != true);
|
|
remains.forEach(res => {
|
|
res.items.forEach(item => delete item.user_data);
|
|
});
|
|
let arr = results.filter(res => res.isIncomplete == true);
|
|
let names = arr.map(o => o.source);
|
|
let { input, colnr, linenr } = this.option;
|
|
Object.assign(this.option, {
|
|
input: resumeInput,
|
|
line: document.getline(linenr - 1),
|
|
colnr: colnr + (resumeInput.length - input.length),
|
|
triggerCharacter: null,
|
|
triggerForInComplete: true
|
|
});
|
|
let sources = this.sources.filter(s => names.indexOf(s.name) !== -1);
|
|
await Promise.all(sources.map(s => this.completeSource(s)));
|
|
return this.filterResults(resumeInput, Math.floor(Date.now() / 1000));
|
|
}
|
|
filterResults(input, cid = 0) {
|
|
let { results } = this;
|
|
results.sort((a, b) => {
|
|
if (a.source == 'tabnine')
|
|
return 1;
|
|
if (b.source == 'tabnine')
|
|
return -1;
|
|
return b.priority - a.priority;
|
|
});
|
|
let now = Date.now();
|
|
let { bufnr } = this.option;
|
|
let { snippetIndicator, removeDuplicateItems, fixInsertedWord } = this.config;
|
|
let followPart = (!fixInsertedWord || cid == 0) ? '' : this.getFollowPart();
|
|
if (results.length == 0)
|
|
return [];
|
|
// max score of high priority source
|
|
let maxScore = 0;
|
|
let arr = [];
|
|
let codes = fuzzy_1.getCharCodes(input);
|
|
let words = new Set();
|
|
for (let i = 0, l = results.length; i < l; i++) {
|
|
let res = results[i];
|
|
let { items, source, priority } = res;
|
|
// tslint:disable-next-line: prefer-for-of
|
|
for (let idx = 0; idx < items.length; idx++) {
|
|
let item = items[idx];
|
|
let { word } = item;
|
|
if ((!item.dup || source == 'tabnine') && words.has(word))
|
|
continue;
|
|
if (removeDuplicateItems && !item.isSnippet && words.has(word))
|
|
continue;
|
|
let filterText = item.filterText || item.word;
|
|
item.filterText = filterText;
|
|
if (filterText.length < input.length)
|
|
continue;
|
|
let score = item.kind && filterText == input ? 64 : match_1.matchScore(filterText, codes);
|
|
if (input.length && score == 0)
|
|
continue;
|
|
if (priority > 90)
|
|
maxScore = Math.max(maxScore, score);
|
|
if (maxScore > 5 && priority <= 10 && score < maxScore)
|
|
continue;
|
|
if (followPart.length && !item.isSnippet) {
|
|
if (item.word.endsWith(followPart)) {
|
|
let { word } = item;
|
|
item.word = item.word.slice(0, -followPart.length);
|
|
item.abbr = item.abbr || word;
|
|
}
|
|
}
|
|
if (!item.user_data) {
|
|
let user_data = { cid, source };
|
|
user_data.index = item.index || idx;
|
|
if (item.isSnippet) {
|
|
let abbr = item.abbr || item.word;
|
|
if (!abbr.endsWith(snippetIndicator)) {
|
|
item.abbr = `${item.abbr || item.word}${snippetIndicator}`;
|
|
}
|
|
}
|
|
if (item.signature)
|
|
user_data.signature = item.signature;
|
|
item.user_data = JSON.stringify(user_data);
|
|
item.source = source;
|
|
let recentScore = this.recentScores[`${bufnr}|${word}`];
|
|
if (recentScore && now - recentScore < 60 * 1000) {
|
|
item.recentScore = recentScore;
|
|
}
|
|
else {
|
|
item.recentScore = 0;
|
|
}
|
|
}
|
|
else {
|
|
delete item.sortText;
|
|
}
|
|
item.priority = priority;
|
|
item.abbr = item.abbr || item.word;
|
|
item.score = input.length ? score : 0;
|
|
item.localBonus = this.localBonus ? this.localBonus.get(filterText) || 0 : 0;
|
|
words.add(word);
|
|
if (item.isSnippet && item.word == input) {
|
|
item.preselect = true;
|
|
}
|
|
arr.push(item);
|
|
}
|
|
}
|
|
arr.sort((a, b) => {
|
|
let sa = a.sortText;
|
|
let sb = b.sortText;
|
|
let wa = a.filterText;
|
|
let wb = b.filterText;
|
|
if (a.score != b.score)
|
|
return b.score - a.score;
|
|
if (a.priority != b.priority)
|
|
return b.priority - a.priority;
|
|
if (sa && sb && sa != sb)
|
|
return sa < sb ? -1 : 1;
|
|
if (a.recentScore != b.recentScore)
|
|
return b.recentScore - a.recentScore;
|
|
if (a.localBonus != b.localBonus) {
|
|
if (a.localBonus && b.localBonus && wa != wb) {
|
|
if (wa.startsWith(wb))
|
|
return 1;
|
|
if (wb.startsWith(wa))
|
|
return -1;
|
|
}
|
|
return b.localBonus - a.localBonus;
|
|
}
|
|
// Default sort method
|
|
switch (this.config.defaultSortMethod) {
|
|
case 'alphabetical':
|
|
return a.filterText.localeCompare(b.filterText);
|
|
case 'length':
|
|
default: // Fallback on length
|
|
return a.filterText.length - b.filterText.length;
|
|
}
|
|
});
|
|
return this.limitCompleteItems(arr.slice(0, this.config.maxItemCount));
|
|
}
|
|
limitCompleteItems(items) {
|
|
let { highPrioritySourceLimit, lowPrioritySourceLimit } = this.config;
|
|
if (!highPrioritySourceLimit && !lowPrioritySourceLimit)
|
|
return items;
|
|
let counts = new Map();
|
|
return items.filter(item => {
|
|
let { priority, source } = item;
|
|
let isLow = priority < 90;
|
|
let curr = counts.get(source) || 0;
|
|
if ((lowPrioritySourceLimit && isLow && curr == lowPrioritySourceLimit)
|
|
|| (highPrioritySourceLimit && !isLow && curr == highPrioritySourceLimit)) {
|
|
return false;
|
|
}
|
|
counts.set(source, curr + 1);
|
|
return true;
|
|
});
|
|
}
|
|
hasMatch(input) {
|
|
let { results } = this;
|
|
if (!results)
|
|
return false;
|
|
let codes = fuzzy_1.getCharCodes(input);
|
|
for (let i = 0, l = results.length; i < l; i++) {
|
|
let items = results[i].items;
|
|
let idx = items.findIndex(item => {
|
|
return fuzzy_1.fuzzyMatch(codes, item.filterText || item.word);
|
|
});
|
|
if (idx !== -1)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
async doComplete() {
|
|
let opts = this.option;
|
|
let { line, colnr, linenr, col } = this.option;
|
|
if (this.config.localityBonus) {
|
|
let line = linenr - 1;
|
|
this.localBonus = this.document.getLocalifyBonus(vscode_languageserver_protocol_1.Position.create(line, opts.col - 1), vscode_languageserver_protocol_1.Position.create(line, colnr));
|
|
}
|
|
else {
|
|
this.localBonus = new Map();
|
|
}
|
|
await Promise.all(this.sources.map(s => this.completeSource(s)));
|
|
let { results } = this;
|
|
if (results.length == 0)
|
|
return [];
|
|
let engrossResult = results.find(r => r.startcol != null && r.startcol != col);
|
|
if (engrossResult) {
|
|
let { startcol } = engrossResult;
|
|
opts.col = startcol;
|
|
opts.input = string_1.byteSlice(line, startcol, colnr - 1);
|
|
this.results = [engrossResult];
|
|
}
|
|
logger.info(`Results from: ${this.results.map(s => s.source).join(',')}`);
|
|
return this.filterResults(opts.input, Math.floor(Date.now() / 1000));
|
|
}
|
|
resolveCompletionItem(item) {
|
|
let { results } = this;
|
|
if (!results)
|
|
return null;
|
|
try {
|
|
if (item.user_data) {
|
|
let { source } = JSON.parse(item.user_data);
|
|
let result = results.find(res => res.source == source);
|
|
return result.items.find(o => o.user_data == item.user_data);
|
|
}
|
|
for (let result of results) {
|
|
let res = result.items.find(o => o.abbr == item.abbr && o.info == item.info);
|
|
if (res)
|
|
return res;
|
|
}
|
|
return null;
|
|
}
|
|
catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
getFollowPart() {
|
|
let { colnr, line } = this.option;
|
|
let idx = string_1.characterIndex(line, colnr - 1);
|
|
if (idx == line.length)
|
|
return '';
|
|
let part = line.slice(idx - line.length);
|
|
return part.match(/^\S?[\w\-]*/)[0];
|
|
}
|
|
dispose() {
|
|
this._onDidComplete.dispose();
|
|
this._canceled = true;
|
|
for (let tokenSource of this.tokenSources.values()) {
|
|
tokenSource.cancel();
|
|
}
|
|
this.tokenSources.clear();
|
|
this.sources = [];
|
|
this.results = [];
|
|
}
|
|
}
|
|
exports.default = Complete;
|
|
//# sourceMappingURL=complete.js.map
|
|
|
|
/***/ }),
|
|
/* 395 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const fuzzy_1 = __webpack_require__(367);
|
|
function nextWordIndex(start = 0, codes) {
|
|
for (let i = start; i < codes.length; i++) {
|
|
if (isWordIndex(i, codes)) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
function upperCase(code) {
|
|
return code >= 65 && code <= 90;
|
|
}
|
|
function isWordIndex(index, codes) {
|
|
if (index == 0)
|
|
return true;
|
|
let curr = codes[index];
|
|
if (!fuzzy_1.wordChar(curr))
|
|
return false;
|
|
let pre = codes[index - 1];
|
|
if (!fuzzy_1.wordChar(pre))
|
|
return true;
|
|
if (upperCase(curr) && !upperCase(pre))
|
|
return true;
|
|
return false;
|
|
}
|
|
/**
|
|
* Rules:
|
|
* - First strict 5, first case match 2.5
|
|
* - First word character strict 2.5, first word character case 2
|
|
* - First fuzzy match strict 1, first fuzzy case 0.5
|
|
* - Follow strict 1, follow case 0.5
|
|
* - Follow word start 1, follow word case 0.75
|
|
* - First fuzzy strict 0.1, first fuzzy case 0.05
|
|
*
|
|
* @public
|
|
* @param {string} word
|
|
* @param {number[]} input
|
|
* @returns {number}
|
|
*/
|
|
function matchScore(word, input) {
|
|
if (input.length == 0 || word.length < input.length)
|
|
return 0;
|
|
let codes = fuzzy_1.getCharCodes(word);
|
|
let curr = codes[0];
|
|
let score = 0;
|
|
let first = input[0];
|
|
let idx = 1;
|
|
let allowFuzzy = true;
|
|
if (!fuzzy_1.wordChar(first)) {
|
|
if (first != codes[0])
|
|
return 0;
|
|
score = 5;
|
|
idx = 1;
|
|
}
|
|
else {
|
|
if (fuzzy_1.caseMatch(first, curr)) {
|
|
score = first == curr ? 5 : 2.5;
|
|
idx = 1;
|
|
}
|
|
else {
|
|
// first word 2.5/2
|
|
let next = nextWordIndex(1, codes);
|
|
if (next != -1) {
|
|
if (fuzzy_1.caseMatch(first, codes[next])) {
|
|
score = first == codes[next] ? 2.5 : 2;
|
|
idx = next + 1;
|
|
}
|
|
}
|
|
if (score == 0) {
|
|
// first fuzzy 1/0.5
|
|
for (let i = 1; i < codes.length; i++) {
|
|
if (fuzzy_1.caseMatch(first, codes[i])) {
|
|
score = first == codes[i] ? 1 : 0.5;
|
|
idx = i + 1;
|
|
allowFuzzy = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (input.length == 1 || score == 0)
|
|
return score;
|
|
let next = nextScore(codes, idx, input.slice(1), allowFuzzy);
|
|
return next == 0 ? 0 : score + next;
|
|
}
|
|
exports.matchScore = matchScore;
|
|
function nextScore(codes, index, inputCodes, allowFuzzy = true) {
|
|
if (index >= codes.length)
|
|
return 0;
|
|
let scores = [];
|
|
let input = inputCodes[0];
|
|
let len = codes.length;
|
|
let isFinal = inputCodes.length == 1;
|
|
if (!fuzzy_1.wordChar(input)) {
|
|
for (let i = index; i < len; i++) {
|
|
if (codes[i] == input) {
|
|
if (isFinal)
|
|
return 1;
|
|
let next = nextScore(codes, i + 1, inputCodes.slice(1), allowFuzzy);
|
|
return next == 0 ? 0 : 1 + next;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
let curr = codes[index];
|
|
let match = fuzzy_1.caseMatch(input, curr);
|
|
if (match) {
|
|
let score = input == curr ? 1 : 0.5;
|
|
if (!isFinal) {
|
|
let next = nextScore(codes, index + 1, inputCodes.slice(1), allowFuzzy);
|
|
score = next == 0 ? 0 : score + next;
|
|
}
|
|
scores.push(score);
|
|
}
|
|
// should not find if current is word index
|
|
if (fuzzy_1.wordChar(input) && !isWordIndex(index, codes)) {
|
|
let idx = nextWordIndex(index + 1, codes);
|
|
if (idx !== -1) {
|
|
let next = codes[idx];
|
|
if (fuzzy_1.caseMatch(input, next)) {
|
|
let score = input == next ? 1 : 0.75;
|
|
if (!isFinal) {
|
|
let next = nextScore(codes, idx + 1, inputCodes.slice(1), allowFuzzy);
|
|
score = next == 0 ? 0 : score + next;
|
|
}
|
|
scores.push(score);
|
|
}
|
|
}
|
|
}
|
|
// find fuzzy
|
|
if (!match && allowFuzzy) {
|
|
for (let i = index + 1; i < len; i++) {
|
|
let code = codes[i];
|
|
if (fuzzy_1.caseMatch(input, code)) {
|
|
let score = input == code ? 0.1 : 0.05;
|
|
if (!isFinal) {
|
|
let next = nextScore(codes, i + 1, inputCodes.slice(1), false);
|
|
score = next == 0 ? 0 : score + next;
|
|
}
|
|
scores.push(score);
|
|
}
|
|
}
|
|
}
|
|
if (!scores.length)
|
|
return 0;
|
|
return Math.max(...scores);
|
|
}
|
|
//# sourceMappingURL=match.js.map
|
|
|
|
/***/ }),
|
|
/* 396 */
|
|
/***/ (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__(318));
|
|
const popup_1 = tslib_1.__importDefault(__webpack_require__(322));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('floating');
|
|
class Floating {
|
|
constructor() {
|
|
let configuration = workspace_1.default.getConfiguration('suggest');
|
|
let enableFloat = configuration.get('floatEnable', true);
|
|
let { env } = workspace_1.default;
|
|
if (enableFloat && !env.floating && !env.textprop) {
|
|
enableFloat = false;
|
|
}
|
|
this.config = {
|
|
srcId: workspace_1.default.createNameSpace('coc-pum-float'),
|
|
maxPreviewWidth: configuration.get('maxPreviewWidth', 80),
|
|
enable: enableFloat
|
|
};
|
|
}
|
|
get buffer() {
|
|
let { floatBuffer } = this;
|
|
return floatBuffer ? floatBuffer.buffer : null;
|
|
}
|
|
async showDocumentationFloating(docs, bounding, token) {
|
|
let { nvim } = workspace_1.default;
|
|
await this.checkBuffer();
|
|
let rect = await this.calculateBounding(docs, bounding);
|
|
let config = Object.assign({ relative: 'editor', }, rect);
|
|
if (this.window) {
|
|
let valid = await this.window.valid;
|
|
if (!valid)
|
|
this.window = null;
|
|
}
|
|
if (token.isCancellationRequested)
|
|
return;
|
|
if (!this.window) {
|
|
try {
|
|
let win = this.window = await nvim.openFloatWindow(this.buffer, false, config);
|
|
if (token.isCancellationRequested) {
|
|
this.close();
|
|
return;
|
|
}
|
|
nvim.pauseNotification();
|
|
win.setVar('float', 1, true);
|
|
win.setVar('popup', 1, true);
|
|
nvim.command(`noa call win_gotoid(${win.id})`, true);
|
|
nvim.command(`setl nospell nolist wrap linebreak foldcolumn=1`, 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);
|
|
this.floatBuffer.setLines();
|
|
nvim.call('cursor', [1, 1], true);
|
|
nvim.command(`noa wincmd p`, true);
|
|
let [, err] = await nvim.resumeNotification();
|
|
// tslint:disable-next-line: no-console
|
|
if (err)
|
|
console.error(`Error on ${err[0]}: ${err[1]} - ${err[2]}`);
|
|
}
|
|
catch (e) {
|
|
logger.error(`Create preview error:`, e.stack);
|
|
}
|
|
}
|
|
else {
|
|
nvim.pauseNotification();
|
|
this.window.setConfig(config, true);
|
|
nvim.command(`noa call win_gotoid(${this.window.id})`, true);
|
|
nvim.call('cursor', [1, 1], true);
|
|
this.floatBuffer.setLines();
|
|
nvim.command(`noa wincmd p`, true);
|
|
let [, err] = await nvim.resumeNotification();
|
|
// tslint:disable-next-line: no-console
|
|
if (err)
|
|
console.error(`Error on ${err[0]}: ${err[1]} - ${err[2]}`);
|
|
}
|
|
}
|
|
async showDocumentationVim(docs, bounding, token) {
|
|
let { nvim } = workspace_1.default;
|
|
await this.checkBuffer();
|
|
let rect = await this.calculateBounding(docs, bounding);
|
|
if (token.isCancellationRequested)
|
|
return this.close();
|
|
nvim.pauseNotification();
|
|
this.floatBuffer.setLines();
|
|
this.popup.move({
|
|
line: rect.row + 1,
|
|
col: rect.col + 1,
|
|
minwidth: rect.width,
|
|
minheight: rect.height,
|
|
maxwidth: rect.width,
|
|
maxheight: rect.height
|
|
});
|
|
this.popup.show();
|
|
nvim.setVar('coc_popup_id', this.popup.id, true);
|
|
nvim.command('redraw', true);
|
|
let [, err] = await nvim.resumeNotification();
|
|
// tslint:disable-next-line: no-console
|
|
if (err)
|
|
console.error(`Error on ${err[0]}: ${err[1]} - ${err[2]}`);
|
|
}
|
|
async show(docs, bounding, token) {
|
|
if (!this.config.enable)
|
|
return;
|
|
if (workspace_1.default.env.floating) {
|
|
await this.showDocumentationFloating(docs, bounding, token);
|
|
}
|
|
else {
|
|
await this.showDocumentationVim(docs, bounding, token);
|
|
}
|
|
}
|
|
async calculateBounding(docs, bounding) {
|
|
// drawn lines
|
|
let { config, floatBuffer } = this;
|
|
let { columns, lines } = workspace_1.default.env;
|
|
let { maxPreviewWidth } = config;
|
|
let pumWidth = bounding.width + (bounding.scrollbar ? 1 : 0);
|
|
let showRight = true;
|
|
let paddingRight = columns - bounding.col - pumWidth;
|
|
if (bounding.col > paddingRight)
|
|
showRight = false;
|
|
let maxWidth = showRight ? paddingRight : bounding.col - 1;
|
|
maxWidth = Math.min(maxPreviewWidth, maxWidth);
|
|
await floatBuffer.setDocuments(docs, maxWidth);
|
|
let maxHeight = lines - bounding.row - workspace_1.default.env.cmdheight - 1;
|
|
return {
|
|
col: showRight ? bounding.col + pumWidth : bounding.col - floatBuffer.width,
|
|
row: bounding.row,
|
|
height: Math.min(maxHeight, floatBuffer.getHeight(docs, maxWidth)),
|
|
width: floatBuffer.width
|
|
};
|
|
}
|
|
async checkBuffer() {
|
|
let { buffer, popup } = this;
|
|
let { nvim } = workspace_1.default;
|
|
if (workspace_1.default.env.textprop) {
|
|
if (popup) {
|
|
let visible = await popup.visible();
|
|
if (!visible) {
|
|
popup.dispose();
|
|
popup = null;
|
|
}
|
|
}
|
|
if (!popup) {
|
|
this.popup = await popup_1.default(nvim, [''], {
|
|
padding: [0, 1, 0, 1],
|
|
highlight: 'CocFloating',
|
|
tab: -1,
|
|
});
|
|
let win = nvim.createWindow(this.popup.id);
|
|
nvim.pauseNotification();
|
|
win.setVar('float', 1, true);
|
|
win.setVar('popup', 1, true);
|
|
win.setOption('linebreak', true, true);
|
|
win.setOption('showbreak', '', true);
|
|
win.setOption('conceallevel', 2, true);
|
|
await nvim.resumeNotification();
|
|
}
|
|
buffer = nvim.createBuffer(this.popup.bufferId);
|
|
this.floatBuffer = new floatBuffer_1.default(nvim, buffer, nvim.createWindow(this.popup.id));
|
|
}
|
|
else {
|
|
if (buffer) {
|
|
let valid = await buffer.valid;
|
|
if (valid)
|
|
return;
|
|
}
|
|
buffer = await nvim.createNewBuffer(false, true);
|
|
await buffer.setOption('buftype', 'nofile');
|
|
await buffer.setOption('bufhidden', 'hide');
|
|
this.floatBuffer = new floatBuffer_1.default(nvim, buffer);
|
|
}
|
|
}
|
|
close() {
|
|
if (workspace_1.default.env.textprop) {
|
|
if (this.popup) {
|
|
this.popup.dispose();
|
|
}
|
|
return;
|
|
}
|
|
let { window } = this;
|
|
if (!window)
|
|
return;
|
|
this.window.close(true, true);
|
|
this.window = null;
|
|
}
|
|
}
|
|
exports.default = Floating;
|
|
//# sourceMappingURL=floating.js.map
|
|
|
|
/***/ }),
|
|
/* 397 */
|
|
/***/ (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__(149);
|
|
const position_1 = __webpack_require__(213);
|
|
const Snippets = tslib_1.__importStar(__webpack_require__(234));
|
|
const string_1 = __webpack_require__(210);
|
|
const logger = __webpack_require__(186)('snippets-snipet');
|
|
class CocSnippet {
|
|
constructor(_snippetString, position, _variableResolver) {
|
|
this._snippetString = _snippetString;
|
|
this.position = position;
|
|
this._variableResolver = _variableResolver;
|
|
this._parser = new Snippets.SnippetParser();
|
|
const snippet = this._parser.parse(this._snippetString, true);
|
|
if (_variableResolver) {
|
|
snippet.resolveVariables(_variableResolver);
|
|
}
|
|
this.tmSnippet = snippet;
|
|
this.update();
|
|
}
|
|
adjustPosition(characterCount, lineCount) {
|
|
let { line, character } = this.position;
|
|
this.position = {
|
|
line: line + lineCount,
|
|
character: character + characterCount
|
|
};
|
|
this.update();
|
|
}
|
|
adjustTextEdit(edit) {
|
|
let { range } = edit;
|
|
if (position_1.comparePosition(this.range.start, range.end) < 0)
|
|
return false;
|
|
if (edit.newText.indexOf('\n') == -1 &&
|
|
this.firstPlaceholder &&
|
|
position_1.comparePosition(this.firstPlaceholder.range.start, this.range.start) == 0 &&
|
|
position_1.comparePosition(range.start, range.end) == 0 &&
|
|
position_1.comparePosition(this.range.start, range.start) == 0) {
|
|
return false;
|
|
}
|
|
let changed = position_1.getChangedPosition(this.range.start, edit);
|
|
if (changed.line == 0 && changed.character == 0)
|
|
return true;
|
|
this.adjustPosition(changed.character, changed.line);
|
|
return true;
|
|
}
|
|
get isPlainText() {
|
|
return this._placeholders.every(p => p.isFinalTabstop && p.value == '');
|
|
}
|
|
toString() {
|
|
return this.tmSnippet.toString();
|
|
}
|
|
get range() {
|
|
let { position } = this;
|
|
const content = this.tmSnippet.toString();
|
|
const doc = vscode_languageserver_protocol_1.TextDocument.create('untitled:/1', 'snippet', 0, content);
|
|
const pos = doc.positionAt(content.length);
|
|
const end = pos.line == 0 ? position.character + pos.character : pos.character;
|
|
return vscode_languageserver_protocol_1.Range.create(position, vscode_languageserver_protocol_1.Position.create(position.line + pos.line, end));
|
|
}
|
|
get firstPlaceholder() {
|
|
return this.getPlaceholder(this.tmSnippet.minIndexNumber);
|
|
}
|
|
get lastPlaceholder() {
|
|
return this.getPlaceholder(this.tmSnippet.maxIndexNumber);
|
|
}
|
|
getPlaceholderById(id) {
|
|
return this._placeholders.find(o => o.id == id);
|
|
}
|
|
getPlaceholder(index) {
|
|
let placeholders = this._placeholders.filter(o => o.index == index);
|
|
let filtered = placeholders.filter(o => !o.transform);
|
|
return filtered.length ? filtered[0] : placeholders[0];
|
|
}
|
|
getPrevPlaceholder(index) {
|
|
if (index == 0)
|
|
return this.lastPlaceholder;
|
|
let prev = this.getPlaceholder(index - 1);
|
|
if (!prev)
|
|
return this.getPrevPlaceholder(index - 1);
|
|
return prev;
|
|
}
|
|
getNextPlaceholder(index) {
|
|
let max = this.tmSnippet.maxIndexNumber;
|
|
if (index == max)
|
|
return this.finalPlaceholder;
|
|
let next = this.getPlaceholder(index + 1);
|
|
if (!next)
|
|
return this.getNextPlaceholder(index + 1);
|
|
return next;
|
|
}
|
|
get finalPlaceholder() {
|
|
return this._placeholders.find(o => o.isFinalTabstop);
|
|
}
|
|
getPlaceholderByRange(range) {
|
|
return this._placeholders.find(o => {
|
|
return position_1.rangeInRange(range, o.range);
|
|
});
|
|
}
|
|
insertSnippet(placeholder, snippet, range) {
|
|
let { start } = placeholder.range;
|
|
// let offset = position.character - start.character
|
|
let editStart = vscode_languageserver_protocol_1.Position.create(range.start.line - start.line, range.start.line == start.line ? range.start.character - start.character : range.start.character);
|
|
let editEnd = vscode_languageserver_protocol_1.Position.create(range.end.line - start.line, range.end.line == start.line ? range.end.character - start.character : range.end.character);
|
|
let editRange = vscode_languageserver_protocol_1.Range.create(editStart, editEnd);
|
|
let first = this.tmSnippet.insertSnippet(snippet, placeholder.id, editRange);
|
|
this.update();
|
|
return first;
|
|
}
|
|
// update internal positions, no change of buffer
|
|
// return TextEdit list when needed
|
|
updatePlaceholder(placeholder, edit) {
|
|
let { start, end } = edit.range;
|
|
let { range } = this;
|
|
let { value, id, index } = placeholder;
|
|
let newText = position_1.editRange(placeholder.range, value, edit);
|
|
let delta = 0;
|
|
if (newText.indexOf('\n') == -1) {
|
|
for (let p of this._placeholders) {
|
|
if (p.index == index &&
|
|
p.id < id &&
|
|
p.line == placeholder.range.start.line) {
|
|
let text = this.tmSnippet.getPlaceholderText(p.id, newText);
|
|
delta = delta + string_1.byteLength(text) - string_1.byteLength(p.value);
|
|
}
|
|
}
|
|
}
|
|
this.tmSnippet.updatePlaceholder(id, newText);
|
|
let endPosition = position_1.adjustPosition(range.end, edit);
|
|
let snippetEdit = {
|
|
range: vscode_languageserver_protocol_1.Range.create(range.start, endPosition),
|
|
newText: this.tmSnippet.toString()
|
|
};
|
|
this.update();
|
|
return { edits: [snippetEdit], delta };
|
|
}
|
|
update() {
|
|
const snippet = this.tmSnippet;
|
|
const placeholders = snippet.placeholders;
|
|
const { line, character } = this.position;
|
|
const document = vscode_languageserver_protocol_1.TextDocument.create('untitled:/1', 'snippet', 0, snippet.toString());
|
|
this._placeholders = placeholders.map((p, idx) => {
|
|
const offset = snippet.offset(p);
|
|
const position = document.positionAt(offset);
|
|
const start = {
|
|
line: line + position.line,
|
|
character: position.line == 0 ? character + position.character : position.character
|
|
};
|
|
const value = p.toString();
|
|
const lines = value.split('\n');
|
|
let res = {
|
|
range: vscode_languageserver_protocol_1.Range.create(start, {
|
|
line: start.line + lines.length - 1,
|
|
character: lines.length == 1 ? start.character + value.length : lines[lines.length - 1].length
|
|
}),
|
|
transform: p.transform != null,
|
|
line: start.line,
|
|
id: idx,
|
|
index: p.index,
|
|
value,
|
|
isFinalTabstop: p.isFinalTabstop,
|
|
snippet: this
|
|
};
|
|
Object.defineProperty(res, 'snippet', {
|
|
enumerable: false
|
|
});
|
|
if (p.choice) {
|
|
let { options } = p.choice;
|
|
if (options && options.length) {
|
|
res.choice = options.map(o => o.value);
|
|
}
|
|
}
|
|
return res;
|
|
});
|
|
}
|
|
}
|
|
exports.CocSnippet = CocSnippet;
|
|
//# sourceMappingURL=snippet.js.map
|
|
|
|
/***/ }),
|
|
/* 398 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const path = tslib_1.__importStar(__webpack_require__(57));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const logger = __webpack_require__(186)('snippets-variable');
|
|
class SnippetVariableResolver {
|
|
constructor() {
|
|
this._variableToValue = {};
|
|
const currentDate = new Date();
|
|
this._variableToValue = {
|
|
CURRENT_YEAR: currentDate.getFullYear().toString(),
|
|
CURRENT_YEAR_SHORT: currentDate
|
|
.getFullYear()
|
|
.toString()
|
|
.slice(-2),
|
|
CURRENT_MONTH: (currentDate.getMonth() + 1).toString(),
|
|
CURRENT_DATE: currentDate.getDate().toString(),
|
|
CURRENT_HOUR: currentDate.getHours().toString(),
|
|
CURRENT_MINUTE: currentDate.getMinutes().toString(),
|
|
CURRENT_SECOND: currentDate.getSeconds().toString(),
|
|
CURRENT_DAY_NAME: currentDate.toLocaleString("en-US", { weekday: "long" }),
|
|
CURRENT_DAY_NAME_SHORT: currentDate.toLocaleString("en-US", { weekday: "short" }),
|
|
CURRENT_MONTH_NAME: currentDate.toLocaleString("en-US", { month: "long" }),
|
|
CURRENT_MONTH_NAME_SHORT: currentDate.toLocaleString("en-US", { month: "short" })
|
|
};
|
|
}
|
|
get nvim() {
|
|
return workspace_1.default.nvim;
|
|
}
|
|
async init(document) {
|
|
let filepath = vscode_uri_1.URI.parse(document.uri).fsPath;
|
|
let [lnum, line, cword, selected, clipboard, yank] = await this.nvim.eval(`[line('.'),getline('.'),expand('<cword>'),get(g:,'coc_selected_text', ''),getreg('+'),getreg('"')]`);
|
|
Object.assign(this._variableToValue, {
|
|
YANK: yank || undefined,
|
|
CLIPBOARD: clipboard || undefined,
|
|
TM_CURRENT_LINE: line,
|
|
TM_SELECTED_TEXT: selected || undefined,
|
|
TM_CURRENT_WORD: cword,
|
|
TM_LINE_INDEX: (lnum - 1).toString(),
|
|
TM_LINE_NUMBER: lnum.toString(),
|
|
TM_FILENAME: path.basename(filepath),
|
|
TM_FILENAME_BASE: path.basename(filepath, path.extname(filepath)),
|
|
TM_DIRECTORY: path.dirname(filepath),
|
|
TM_FILEPATH: filepath,
|
|
});
|
|
}
|
|
resolve(variable) {
|
|
const variableName = variable.name;
|
|
if (this._variableToValue.hasOwnProperty(variableName)) {
|
|
return this._variableToValue[variableName] || '';
|
|
}
|
|
if (variable.children && variable.children.length) {
|
|
return variable.toString();
|
|
}
|
|
return variableName;
|
|
}
|
|
}
|
|
exports.SnippetVariableResolver = SnippetVariableResolver;
|
|
//# sourceMappingURL=variableResolve.js.map
|
|
|
|
/***/ }),
|
|
/* 399 */
|
|
/***/ (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__(149);
|
|
const commands_1 = tslib_1.__importDefault(__webpack_require__(232));
|
|
const manager_1 = tslib_1.__importDefault(__webpack_require__(316));
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const languages_1 = tslib_1.__importDefault(__webpack_require__(315));
|
|
const manager_2 = tslib_1.__importDefault(__webpack_require__(364));
|
|
const floatFactory_1 = tslib_1.__importDefault(__webpack_require__(317));
|
|
const services_1 = tslib_1.__importDefault(__webpack_require__(351));
|
|
const manager_3 = tslib_1.__importDefault(__webpack_require__(233));
|
|
const util_1 = __webpack_require__(174);
|
|
const convert_1 = __webpack_require__(379);
|
|
const object_1 = __webpack_require__(190);
|
|
const position_1 = __webpack_require__(213);
|
|
const string_1 = __webpack_require__(210);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const codelens_1 = tslib_1.__importDefault(__webpack_require__(400));
|
|
const colors_1 = tslib_1.__importDefault(__webpack_require__(401));
|
|
const documentHighlight_1 = tslib_1.__importDefault(__webpack_require__(403));
|
|
const refactor_1 = tslib_1.__importDefault(__webpack_require__(404));
|
|
const search_1 = tslib_1.__importDefault(__webpack_require__(405));
|
|
const debounce = __webpack_require__(176);
|
|
const logger = __webpack_require__(186)('Handler');
|
|
const pairs = new Map([
|
|
['<', '>'],
|
|
['>', '<'],
|
|
['{', '}'],
|
|
['[', ']'],
|
|
['(', ')'],
|
|
]);
|
|
class Handler {
|
|
constructor(nvim) {
|
|
this.nvim = nvim;
|
|
this.refactorMap = new Map();
|
|
this.documentLines = [];
|
|
this.disposables = [];
|
|
this.labels = {};
|
|
this.selectionRange = null;
|
|
this.getPreferences();
|
|
workspace_1.default.onDidChangeConfiguration(e => {
|
|
if (e.affectsConfiguration('coc.preferences')) {
|
|
this.getPreferences();
|
|
}
|
|
});
|
|
this.hoverFactory = new floatFactory_1.default(nvim, workspace_1.default.env);
|
|
this.disposables.push(this.hoverFactory);
|
|
let { signaturePreferAbove, signatureFloatMaxWidth, signatureMaxHeight } = this.preferences;
|
|
this.signatureFactory = new floatFactory_1.default(nvim, workspace_1.default.env, signaturePreferAbove, signatureMaxHeight, signatureFloatMaxWidth, false);
|
|
this.disposables.push(this.signatureFactory);
|
|
events_1.default.on('BufUnload', async (bufnr) => {
|
|
let refactor = this.refactorMap.get(bufnr);
|
|
if (refactor) {
|
|
refactor.dispose();
|
|
this.refactorMap.delete(bufnr);
|
|
}
|
|
}, null, this.disposables);
|
|
events_1.default.on('CursorMovedI', async (bufnr, cursor) => {
|
|
if (!this.signaturePosition)
|
|
return;
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return;
|
|
let { line, character } = this.signaturePosition;
|
|
if (cursor[0] - 1 == line) {
|
|
let currline = doc.getline(cursor[0] - 1);
|
|
let col = string_1.byteLength(currline.slice(0, character)) + 1;
|
|
if (cursor[1] > col)
|
|
return;
|
|
}
|
|
this.signatureFactory.close();
|
|
}, null, this.disposables);
|
|
events_1.default.on('InsertLeave', () => {
|
|
this.signatureFactory.close();
|
|
}, null, this.disposables);
|
|
events_1.default.on(['TextChangedI', 'TextChangedP'], async () => {
|
|
if (this.preferences.signatureHideOnChange) {
|
|
this.signatureFactory.close();
|
|
}
|
|
this.hoverFactory.close();
|
|
}, null, this.disposables);
|
|
let lastInsert;
|
|
events_1.default.on('InsertCharPre', async (character) => {
|
|
lastInsert = Date.now();
|
|
if (character == ')')
|
|
this.signatureFactory.close();
|
|
}, null, this.disposables);
|
|
events_1.default.on('Enter', async (bufnr) => {
|
|
let { bracketEnterImprove } = this.preferences;
|
|
await this.onCharacterType('\n', bufnr);
|
|
if (bracketEnterImprove) {
|
|
let line = await nvim.call('line', '.') - 1;
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return;
|
|
let pre = doc.getline(line - 1);
|
|
let curr = doc.getline(line);
|
|
let prevChar = pre[pre.length - 1];
|
|
if (prevChar && pairs.has(prevChar)) {
|
|
let nextChar = curr.trim()[0];
|
|
if (nextChar && pairs.get(prevChar) == nextChar) {
|
|
let edits = [];
|
|
let opts = await workspace_1.default.getFormatOptions(doc.uri);
|
|
let space = opts.insertSpaces ? ' '.repeat(opts.tabSize) : '\t';
|
|
let preIndent = pre.match(/^\s*/)[0];
|
|
let currIndent = curr.match(/^\s*/)[0];
|
|
let newText = '\n' + preIndent + space;
|
|
let pos = vscode_languageserver_protocol_1.Position.create(line - 1, pre.length);
|
|
// make sure indent of current line
|
|
if (preIndent != currIndent) {
|
|
let newText = doc.filetype == 'vim' ? ' \\ ' + preIndent : preIndent;
|
|
edits.push({ range: vscode_languageserver_protocol_1.Range.create(vscode_languageserver_protocol_1.Position.create(line, 0), vscode_languageserver_protocol_1.Position.create(line, currIndent.length)), newText });
|
|
}
|
|
else if (doc.filetype == 'vim') {
|
|
edits.push({ range: vscode_languageserver_protocol_1.Range.create(line, currIndent.length, line, currIndent.length), newText: ' \\ ' });
|
|
}
|
|
if (doc.filetype == 'vim') {
|
|
newText = newText + '\\ ';
|
|
}
|
|
edits.push({ range: vscode_languageserver_protocol_1.Range.create(pos, pos), newText });
|
|
await doc.applyEdits(nvim, edits);
|
|
await workspace_1.default.moveTo(vscode_languageserver_protocol_1.Position.create(line, newText.length - 1));
|
|
}
|
|
}
|
|
}
|
|
}, null, this.disposables);
|
|
events_1.default.on('TextChangedI', async (bufnr) => {
|
|
let curr = Date.now();
|
|
if (!lastInsert || curr - lastInsert > 500)
|
|
return;
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return;
|
|
let { triggerSignatureHelp, triggerSignatureWait, formatOnType } = this.preferences;
|
|
if (!triggerSignatureHelp && !formatOnType)
|
|
return;
|
|
let [pos, line] = await nvim.eval('[coc#util#cursor(), getline(".")]');
|
|
let pre = pos[1] == 0 ? '' : line.slice(pos[1] - 1, pos[1]);
|
|
if (!pre || string_1.isWord(pre))
|
|
return;
|
|
if (!doc.paused)
|
|
await this.onCharacterType(pre, bufnr);
|
|
if (triggerSignatureHelp && languages_1.default.shouldTriggerSignatureHelp(doc.textDocument, pre)) {
|
|
doc.forceSync();
|
|
await util_1.wait(Math.min(Math.max(triggerSignatureWait, 50), 300));
|
|
if (!workspace_1.default.insertMode)
|
|
return;
|
|
try {
|
|
let cursor = await nvim.call('coc#util#cursor');
|
|
await this.triggerSignatureHelp(doc, { line: cursor[0], character: cursor[1] });
|
|
}
|
|
catch (e) {
|
|
logger.error(`Error on signature help:`, e);
|
|
}
|
|
}
|
|
}, null, this.disposables);
|
|
events_1.default.on('InsertLeave', async (bufnr) => {
|
|
await util_1.wait(30);
|
|
if (workspace_1.default.insertMode)
|
|
return;
|
|
await this.onCharacterType('\n', bufnr, true);
|
|
}, null, this.disposables);
|
|
events_1.default.on('CursorMoved', debounce((bufnr, cursor) => {
|
|
if (!this.preferences.previewAutoClose || !this.hoverPosition)
|
|
return;
|
|
if (this.preferences.hoverTarget == 'float')
|
|
return;
|
|
let arr = [bufnr, cursor[0], cursor[1]];
|
|
if (object_1.equals(arr, this.hoverPosition))
|
|
return;
|
|
let doc = workspace_1.default.documents.find(doc => doc.uri.startsWith('coc://'));
|
|
if (doc && doc.bufnr != bufnr) {
|
|
nvim.command('pclose', true);
|
|
}
|
|
}, 100), null, this.disposables);
|
|
if (this.preferences.currentFunctionSymbolAutoUpdate) {
|
|
events_1.default.on('CursorHold', async () => {
|
|
try {
|
|
await this.getCurrentFunctionSymbol();
|
|
}
|
|
catch (e) {
|
|
logger.error(e);
|
|
}
|
|
}, null, this.disposables);
|
|
}
|
|
let provider = {
|
|
onDidChange: null,
|
|
provideTextDocumentContent: async () => {
|
|
nvim.pauseNotification();
|
|
nvim.command('setlocal conceallevel=2 nospell nofoldenable wrap', true);
|
|
nvim.command('setlocal bufhidden=wipe nobuflisted', true);
|
|
nvim.command('setfiletype markdown', true);
|
|
nvim.command(`exe "normal! z${this.documentLines.length}\\<cr>"`, true);
|
|
await nvim.resumeNotification();
|
|
return this.documentLines.join('\n');
|
|
}
|
|
};
|
|
this.disposables.push(workspace_1.default.registerTextDocumentContentProvider('coc', provider));
|
|
this.codeLensManager = new codelens_1.default(nvim);
|
|
this.colors = new colors_1.default(nvim);
|
|
this.documentHighlighter = new documentHighlight_1.default(nvim, this.colors);
|
|
this.disposables.push(commands_1.default.registerCommand('editor.action.organizeImport', async (bufnr) => {
|
|
if (!bufnr)
|
|
bufnr = await nvim.call('bufnr', '%');
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return false;
|
|
let range = vscode_languageserver_protocol_1.Range.create(0, 0, doc.lineCount, 0);
|
|
let actions = await this.getCodeActions(bufnr, range, [vscode_languageserver_protocol_1.CodeActionKind.SourceOrganizeImports]);
|
|
if (actions && actions.length) {
|
|
await this.applyCodeAction(actions[0]);
|
|
return true;
|
|
}
|
|
workspace_1.default.showMessage(`Orgnize import action not found.`, 'warning');
|
|
return false;
|
|
}));
|
|
commands_1.default.titles.set('editor.action.organizeImport', 'run organize import code action.');
|
|
}
|
|
async getCurrentFunctionSymbol() {
|
|
let position = await workspace_1.default.getCursorPosition();
|
|
let buffer = await this.nvim.buffer;
|
|
let document = workspace_1.default.getDocument(buffer.id);
|
|
if (!document)
|
|
return;
|
|
let symbols = await this.getDocumentSymbols(document);
|
|
if (!symbols || symbols.length === 0) {
|
|
buffer.setVar('coc_current_function', '', true);
|
|
this.nvim.call('coc#util#do_autocmd', ['CocStatusChange'], true);
|
|
return '';
|
|
}
|
|
symbols = symbols.filter(s => [
|
|
'Class',
|
|
'Method',
|
|
'Function',
|
|
].includes(s.kind));
|
|
let functionName = '';
|
|
for (let sym of symbols.reverse()) {
|
|
if (sym.range
|
|
&& position_1.positionInRange(position, sym.range) == 0
|
|
&& !sym.text.endsWith(') callback')) {
|
|
functionName = sym.text;
|
|
let label = this.labels[sym.kind.toLowerCase()];
|
|
if (label)
|
|
functionName = `${label} ${functionName}`;
|
|
break;
|
|
}
|
|
}
|
|
buffer.setVar('coc_current_function', functionName, true);
|
|
this.nvim.call('coc#util#do_autocmd', ['CocStatusChange'], true);
|
|
return functionName;
|
|
}
|
|
async hasProvider(id) {
|
|
let bufnr = await this.nvim.call('bufnr', '%');
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return false;
|
|
return languages_1.default.hasProvider(id, doc.textDocument);
|
|
}
|
|
async onHover() {
|
|
let { document, position } = await workspace_1.default.getCurrentState();
|
|
let hovers = await languages_1.default.getHover(document, position);
|
|
if (hovers && hovers.length) {
|
|
let hover = hovers.find(o => vscode_languageserver_protocol_1.Range.is(o.range));
|
|
if (hover) {
|
|
let doc = workspace_1.default.getDocument(document.uri);
|
|
if (doc) {
|
|
let ids = doc.matchAddRanges([hover.range], 'CocHoverRange', 999);
|
|
setTimeout(() => {
|
|
this.nvim.call('coc#util#clearmatches', [ids], true);
|
|
}, 1000);
|
|
}
|
|
}
|
|
await this.previewHover(hovers);
|
|
return true;
|
|
}
|
|
let target = this.preferences.hoverTarget;
|
|
if (target == 'float') {
|
|
this.hoverFactory.close();
|
|
}
|
|
else if (target == 'preview') {
|
|
this.nvim.command('pclose', true);
|
|
}
|
|
return false;
|
|
}
|
|
async gotoDefinition(openCommand) {
|
|
let { document, position } = await workspace_1.default.getCurrentState();
|
|
let definition = await languages_1.default.getDefinition(document, position);
|
|
if (isEmpty(definition)) {
|
|
this.onEmptyLocation('Definition', definition);
|
|
return false;
|
|
}
|
|
await this.handleLocations(definition, openCommand);
|
|
return true;
|
|
}
|
|
async gotoDeclaration(openCommand) {
|
|
let { document, position } = await workspace_1.default.getCurrentState();
|
|
let definition = await languages_1.default.getDeclaration(document, position);
|
|
if (isEmpty(definition)) {
|
|
this.onEmptyLocation('Declaration', definition);
|
|
return false;
|
|
}
|
|
await this.handleLocations(definition, openCommand);
|
|
return true;
|
|
}
|
|
async gotoTypeDefinition(openCommand) {
|
|
let { document, position } = await workspace_1.default.getCurrentState();
|
|
let definition = await languages_1.default.getTypeDefinition(document, position);
|
|
if (isEmpty(definition)) {
|
|
this.onEmptyLocation('Type definition', definition);
|
|
return false;
|
|
}
|
|
await this.handleLocations(definition, openCommand);
|
|
return true;
|
|
}
|
|
async gotoImplementation(openCommand) {
|
|
let { document, position } = await workspace_1.default.getCurrentState();
|
|
let definition = await languages_1.default.getImplementation(document, position);
|
|
if (isEmpty(definition)) {
|
|
this.onEmptyLocation('Implementation', definition);
|
|
return false;
|
|
}
|
|
await this.handleLocations(definition, openCommand);
|
|
return true;
|
|
}
|
|
async gotoReferences(openCommand) {
|
|
let { document, position } = await workspace_1.default.getCurrentState();
|
|
let locs = await languages_1.default.getReferences(document, { includeDeclaration: false }, position);
|
|
if (isEmpty(locs)) {
|
|
this.onEmptyLocation('References', locs);
|
|
return false;
|
|
}
|
|
await this.handleLocations(locs, openCommand);
|
|
return true;
|
|
}
|
|
async getDocumentSymbols(document) {
|
|
document = document || workspace_1.default.getDocument(workspace_1.default.bufnr);
|
|
if (!document)
|
|
return [];
|
|
let symbols = await languages_1.default.getDocumentSymbol(document.textDocument);
|
|
if (!symbols)
|
|
return null;
|
|
if (symbols.length == 0)
|
|
return [];
|
|
let level = 0;
|
|
let res = [];
|
|
let pre = null;
|
|
if (isDocumentSymbols(symbols)) {
|
|
symbols.sort(sortDocumentSymbols);
|
|
symbols.forEach(s => addDoucmentSymbol(res, s, level));
|
|
}
|
|
else {
|
|
symbols.sort(sortSymbolInformations);
|
|
for (let sym of symbols) {
|
|
let { name, kind, location, containerName } = sym;
|
|
if (!containerName || !pre) {
|
|
level = 0;
|
|
}
|
|
else {
|
|
if (pre.containerName == containerName) {
|
|
level = pre.level || 0;
|
|
}
|
|
else {
|
|
let container = getPreviousContainer(containerName, res);
|
|
level = container ? container.level + 1 : 0;
|
|
}
|
|
}
|
|
let { start } = location.range;
|
|
let o = {
|
|
col: start.character + 1,
|
|
lnum: start.line + 1,
|
|
text: name,
|
|
level,
|
|
kind: convert_1.getSymbolKind(kind),
|
|
range: location.range,
|
|
containerName
|
|
};
|
|
res.push(o);
|
|
pre = o;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
async getWordEdit() {
|
|
let bufnr = await this.nvim.call('bufnr', '%');
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return null;
|
|
let position = await workspace_1.default.getCursorPosition();
|
|
let range = doc.getWordRangeAtPosition(position);
|
|
if (!range || position_1.emptyRange(range))
|
|
return null;
|
|
let curname = doc.textDocument.getText(range);
|
|
if (languages_1.default.hasProvider('rename', doc.textDocument)) {
|
|
if (doc.dirty) {
|
|
doc.forceSync();
|
|
await util_1.wait(30);
|
|
}
|
|
let res = await languages_1.default.prepareRename(doc.textDocument, position);
|
|
if (res === false)
|
|
return null;
|
|
let edit = await languages_1.default.provideRenameEdits(doc.textDocument, position, curname);
|
|
if (edit)
|
|
return edit;
|
|
}
|
|
workspace_1.default.showMessage('Rename provider not found, extract word ranges from current buffer', 'more');
|
|
let ranges = doc.getSymbolRanges(curname);
|
|
return {
|
|
changes: {
|
|
[doc.uri]: ranges.map(r => {
|
|
return { range: r, newText: curname };
|
|
})
|
|
}
|
|
};
|
|
}
|
|
async rename(newName) {
|
|
let bufnr = await this.nvim.call('bufnr', '%');
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return false;
|
|
let { nvim } = this;
|
|
let position = await workspace_1.default.getCursorPosition();
|
|
let range = doc.getWordRangeAtPosition(position);
|
|
if (!range || position_1.emptyRange(range))
|
|
return false;
|
|
if (!languages_1.default.hasProvider('rename', doc.textDocument)) {
|
|
workspace_1.default.showMessage(`Rename provider not found for current document`, 'error');
|
|
return false;
|
|
}
|
|
if (doc.dirty) {
|
|
doc.forceSync();
|
|
await util_1.wait(30);
|
|
}
|
|
let res = await languages_1.default.prepareRename(doc.textDocument, position);
|
|
if (res === false) {
|
|
workspace_1.default.showMessage('Invalid position for renmame', 'error');
|
|
return false;
|
|
}
|
|
if (!newName) {
|
|
let curname = await nvim.eval('expand("<cword>")');
|
|
newName = await workspace_1.default.callAsync('input', ['New name: ', curname]);
|
|
nvim.command('normal! :<C-u>', true);
|
|
if (!newName) {
|
|
workspace_1.default.showMessage('Empty name, canceled', 'warning');
|
|
return false;
|
|
}
|
|
}
|
|
let edit = await languages_1.default.provideRenameEdits(doc.textDocument, position, newName);
|
|
if (!edit) {
|
|
workspace_1.default.showMessage('Invalid position for rename', 'warning');
|
|
return false;
|
|
}
|
|
await workspace_1.default.applyEdit(edit);
|
|
return true;
|
|
}
|
|
async documentFormatting() {
|
|
let bufnr = await this.nvim.eval('bufnr("%")');
|
|
let document = workspace_1.default.getDocument(bufnr);
|
|
if (!document)
|
|
return false;
|
|
let options = await workspace_1.default.getFormatOptions(document.uri);
|
|
let textEdits = await languages_1.default.provideDocumentFormattingEdits(document.textDocument, options);
|
|
if (!textEdits || textEdits.length == 0)
|
|
return false;
|
|
await document.applyEdits(this.nvim, textEdits);
|
|
return true;
|
|
}
|
|
async documentRangeFormatting(mode) {
|
|
let document = await workspace_1.default.document;
|
|
if (!document)
|
|
return -1;
|
|
let range;
|
|
if (mode) {
|
|
range = await workspace_1.default.getSelectedRange(mode, document);
|
|
if (!range)
|
|
return -1;
|
|
}
|
|
else {
|
|
let lnum = await this.nvim.getVvar('lnum');
|
|
let count = await this.nvim.getVvar('count');
|
|
let mode = await this.nvim.call('mode');
|
|
// we can't handle
|
|
if (count == 0 || mode == 'i' || mode == 'R')
|
|
return -1;
|
|
range = vscode_languageserver_protocol_1.Range.create(lnum - 1, 0, lnum - 1 + count, 0);
|
|
}
|
|
let options = await workspace_1.default.getFormatOptions(document.uri);
|
|
let textEdits = await languages_1.default.provideDocumentRangeFormattingEdits(document.textDocument, range, options);
|
|
if (!textEdits)
|
|
return -1;
|
|
await document.applyEdits(this.nvim, textEdits);
|
|
return 0;
|
|
}
|
|
async runCommand(id, ...args) {
|
|
if (id) {
|
|
await events_1.default.fire('Command', [id]);
|
|
let res = await commands_1.default.executeCommand(id, ...args);
|
|
if (args.length == 0) {
|
|
await commands_1.default.addRecent(id);
|
|
}
|
|
return res;
|
|
}
|
|
else {
|
|
await manager_2.default.start(['commands']);
|
|
}
|
|
}
|
|
async getCodeActions(bufnr, range, only) {
|
|
let document = workspace_1.default.getDocument(bufnr);
|
|
if (!document)
|
|
return [];
|
|
if (!range) {
|
|
let lnum = await this.nvim.call('line', ['.']);
|
|
range = {
|
|
start: { line: lnum - 1, character: 0 },
|
|
end: { line: lnum, character: 0 }
|
|
};
|
|
}
|
|
let diagnostics = manager_1.default.getDiagnosticsInRange(document.textDocument, range);
|
|
let context = { diagnostics };
|
|
if (only && Array.isArray(only))
|
|
context.only = only;
|
|
let codeActionsMap = await languages_1.default.getCodeActions(document.textDocument, range, context);
|
|
if (!codeActionsMap)
|
|
return [];
|
|
let codeActions = [];
|
|
for (let clientId of codeActionsMap.keys()) {
|
|
let actions = codeActionsMap.get(clientId);
|
|
for (let action of actions) {
|
|
codeActions.push(Object.assign({ clientId }, action));
|
|
}
|
|
}
|
|
codeActions.sort((a, b) => {
|
|
if (a.isPrefered && !b.isPrefered) {
|
|
return -1;
|
|
}
|
|
if (b.isPrefered && !a.isPrefered) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
});
|
|
return codeActions;
|
|
}
|
|
async doCodeAction(mode, only) {
|
|
let bufnr = await this.nvim.call('bufnr', '%');
|
|
let range;
|
|
if (mode)
|
|
range = await workspace_1.default.getSelectedRange(mode, workspace_1.default.getDocument(bufnr));
|
|
let codeActions = await this.getCodeActions(bufnr, range, Array.isArray(only) ? only : null);
|
|
if (!codeActions || codeActions.length == 0) {
|
|
workspace_1.default.showMessage('No action available', 'warning');
|
|
return;
|
|
}
|
|
if (only && typeof only == 'string') {
|
|
let action = codeActions.find(o => o.title == only || (o.command && o.command.title == only));
|
|
if (!action)
|
|
return workspace_1.default.showMessage(`action "${only}" not found.`, 'warning');
|
|
await this.applyCodeAction(action);
|
|
}
|
|
else {
|
|
let idx = await workspace_1.default.showQuickpick(codeActions.map(o => o.title));
|
|
if (idx == -1)
|
|
return;
|
|
let action = codeActions[idx];
|
|
if (action)
|
|
await this.applyCodeAction(action);
|
|
}
|
|
}
|
|
/**
|
|
* Get current codeActions
|
|
*
|
|
* @public
|
|
* @returns {Promise<CodeAction[]>}
|
|
*/
|
|
async getCurrentCodeActions(mode, only) {
|
|
let bufnr = await this.nvim.call('bufnr', '%');
|
|
let document = workspace_1.default.getDocument(bufnr);
|
|
if (!document)
|
|
return [];
|
|
let range;
|
|
if (mode)
|
|
range = await workspace_1.default.getSelectedRange(mode, workspace_1.default.getDocument(bufnr));
|
|
return await this.getCodeActions(bufnr, range, only);
|
|
}
|
|
async doQuickfix() {
|
|
let actions = await this.getCurrentCodeActions(null, [vscode_languageserver_protocol_1.CodeActionKind.QuickFix]);
|
|
if (!actions || actions.length == 0) {
|
|
workspace_1.default.showMessage('No quickfix action available', 'warning');
|
|
return false;
|
|
}
|
|
await this.applyCodeAction(actions[0]);
|
|
await this.nvim.command(`silent! call repeat#set("\\<Plug>(coc-fix-current)", -1)`);
|
|
return true;
|
|
}
|
|
async applyCodeAction(action) {
|
|
let { command, edit } = action;
|
|
if (edit)
|
|
await workspace_1.default.applyEdit(edit);
|
|
if (command) {
|
|
if (commands_1.default.has(command.command)) {
|
|
commands_1.default.execute(command);
|
|
}
|
|
else {
|
|
let clientId = action.clientId;
|
|
let service = services_1.default.getService(clientId);
|
|
let params = {
|
|
command: command.command,
|
|
arguments: command.arguments
|
|
};
|
|
if (service.client) {
|
|
let { client } = service;
|
|
client
|
|
.sendRequest(vscode_languageserver_protocol_1.ExecuteCommandRequest.type, params)
|
|
.then(undefined, error => {
|
|
workspace_1.default.showMessage(`Execute '${command.command} error: ${error}'`, 'error');
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
async doCodeLensAction() {
|
|
await this.codeLensManager.doAction();
|
|
}
|
|
async fold(kind) {
|
|
let document = await workspace_1.default.document;
|
|
let win = await this.nvim.window;
|
|
let foldmethod = await win.getOption('foldmethod');
|
|
if (foldmethod != 'manual') {
|
|
workspace_1.default.showMessage('foldmethod option should be manual!', 'warning');
|
|
return false;
|
|
}
|
|
let ranges = await languages_1.default.provideFoldingRanges(document.textDocument, {});
|
|
if (ranges == null) {
|
|
workspace_1.default.showMessage('no range provider found', 'warning');
|
|
return false;
|
|
}
|
|
if (!ranges || ranges.length == 0) {
|
|
workspace_1.default.showMessage('no range found', 'warning');
|
|
return false;
|
|
}
|
|
if (kind) {
|
|
ranges = ranges.filter(o => o.kind == kind);
|
|
}
|
|
if (ranges && ranges.length) {
|
|
await win.setOption('foldenable', true);
|
|
for (let range of ranges.reverse()) {
|
|
let { startLine, endLine } = range;
|
|
let cmd = `${startLine + 1}, ${endLine + 1}fold`;
|
|
this.nvim.command(cmd, true);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
async pickColor() {
|
|
await this.colors.pickColor();
|
|
}
|
|
async pickPresentation() {
|
|
await this.colors.pickPresentation();
|
|
}
|
|
async highlight() {
|
|
let bufnr = await this.nvim.call('bufnr', '%');
|
|
await this.documentHighlighter.highlight(bufnr);
|
|
}
|
|
async getSymbolsRanges() {
|
|
let document = await workspace_1.default.document;
|
|
let highlights = await this.documentHighlighter.getHighlights(document);
|
|
if (!highlights)
|
|
return null;
|
|
return highlights.map(o => o.range);
|
|
}
|
|
async links() {
|
|
let doc = await workspace_1.default.document;
|
|
let links = await languages_1.default.getDocumentLinks(doc.textDocument);
|
|
links = links || [];
|
|
let res = [];
|
|
for (let link of links) {
|
|
if (link.target) {
|
|
res.push(link);
|
|
}
|
|
else {
|
|
link = await languages_1.default.resolveDocumentLink(link);
|
|
res.push(link);
|
|
}
|
|
}
|
|
return links;
|
|
}
|
|
async openLink() {
|
|
let { document, position } = await workspace_1.default.getCurrentState();
|
|
let links = await languages_1.default.getDocumentLinks(document);
|
|
if (!links || links.length == 0)
|
|
return false;
|
|
for (let link of links) {
|
|
if (position_1.positionInRange(position, link.range)) {
|
|
let { target } = link;
|
|
if (!target) {
|
|
link = await languages_1.default.resolveDocumentLink(link);
|
|
target = link.target;
|
|
}
|
|
if (target) {
|
|
await workspace_1.default.openResource(target);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
async getCommands() {
|
|
let list = commands_1.default.commandList;
|
|
let res = [];
|
|
let { titles } = commands_1.default;
|
|
for (let item of list) {
|
|
res.push({
|
|
id: item.id,
|
|
title: titles.get(item.id) || ''
|
|
});
|
|
}
|
|
return res;
|
|
}
|
|
async selectFunction(inner, visualmode) {
|
|
let { nvim } = this;
|
|
let bufnr = await nvim.eval('bufnr("%")');
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return;
|
|
let range;
|
|
if (visualmode) {
|
|
range = await workspace_1.default.getSelectedRange(visualmode, doc);
|
|
}
|
|
else {
|
|
let pos = await workspace_1.default.getCursorPosition();
|
|
range = vscode_languageserver_protocol_1.Range.create(pos, pos);
|
|
}
|
|
let symbols = await this.getDocumentSymbols(doc);
|
|
if (!symbols || symbols.length === 0) {
|
|
workspace_1.default.showMessage('No symbols found', 'warning');
|
|
return;
|
|
}
|
|
let properties = symbols.filter(s => s.kind == 'Property');
|
|
symbols = symbols.filter(s => [
|
|
'Method',
|
|
'Function',
|
|
].includes(s.kind));
|
|
let selectRange;
|
|
for (let sym of symbols.reverse()) {
|
|
if (sym.range && !object_1.equals(sym.range, range) && position_1.rangeInRange(range, sym.range)) {
|
|
selectRange = sym.range;
|
|
break;
|
|
}
|
|
}
|
|
if (!selectRange) {
|
|
for (let sym of properties) {
|
|
if (sym.range && !object_1.equals(sym.range, range) && position_1.rangeInRange(range, sym.range)) {
|
|
selectRange = sym.range;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (inner && selectRange) {
|
|
let { start, end } = selectRange;
|
|
let line = doc.getline(start.line + 1);
|
|
let endLine = doc.getline(end.line - 1);
|
|
selectRange = vscode_languageserver_protocol_1.Range.create(start.line + 1, line.match(/^\s*/)[0].length, end.line - 1, endLine.length);
|
|
}
|
|
if (selectRange)
|
|
await workspace_1.default.selectRange(selectRange);
|
|
}
|
|
async onCharacterType(ch, bufnr, insertLeave = false) {
|
|
if (!ch || string_1.isWord(ch) || !this.preferences.formatOnType)
|
|
return;
|
|
if (manager_3.default.getSession(bufnr) != null)
|
|
return;
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc || doc.paused)
|
|
return;
|
|
if (!languages_1.default.hasOnTypeProvider(ch, doc.textDocument))
|
|
return;
|
|
let position = await workspace_1.default.getCursorPosition();
|
|
let origLine = doc.getline(position.line);
|
|
let { changedtick, dirty } = doc;
|
|
if (dirty) {
|
|
doc.forceSync();
|
|
await util_1.wait(50);
|
|
}
|
|
let pos = insertLeave ? { line: position.line + 1, character: 0 } : position;
|
|
try {
|
|
let edits = await languages_1.default.provideDocumentOnTypeEdits(ch, doc.textDocument, pos);
|
|
// changed by other process
|
|
if (doc.changedtick != changedtick)
|
|
return;
|
|
if (insertLeave) {
|
|
edits = edits.filter(edit => {
|
|
return edit.range.start.line < position.line + 1;
|
|
});
|
|
}
|
|
if (edits && edits.length) {
|
|
await doc.applyEdits(this.nvim, edits);
|
|
let newLine = doc.getline(position.line);
|
|
if (newLine.length > origLine.length) {
|
|
let character = position.character + (newLine.length - origLine.length);
|
|
await workspace_1.default.moveTo(vscode_languageserver_protocol_1.Position.create(position.line, character));
|
|
}
|
|
}
|
|
}
|
|
catch (e) {
|
|
if (!/timeout\s/.test(e.message)) {
|
|
console.error(`Error on formatOnType: ${e.message}`); // tslint:disable-line
|
|
}
|
|
}
|
|
}
|
|
async triggerSignatureHelp(document, position) {
|
|
if (this.signatureTokenSource) {
|
|
this.signatureTokenSource.cancel();
|
|
this.signatureTokenSource = null;
|
|
}
|
|
let part = document.getline(position.line).slice(0, position.character);
|
|
if (part.endsWith(')')) {
|
|
this.signatureFactory.close();
|
|
return;
|
|
}
|
|
let idx = Math.max(part.lastIndexOf(','), part.lastIndexOf('('));
|
|
if (idx != -1)
|
|
position.character = idx + 1;
|
|
let tokenSource = this.signatureTokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource();
|
|
let token = tokenSource.token;
|
|
let timer = setTimeout(() => {
|
|
if (!token.isCancellationRequested) {
|
|
tokenSource.cancel();
|
|
}
|
|
}, 3000);
|
|
let signatureHelp = await languages_1.default.getSignatureHelp(document.textDocument, position, token);
|
|
clearTimeout(timer);
|
|
if (token.isCancellationRequested || !signatureHelp || signatureHelp.signatures.length == 0) {
|
|
this.signatureFactory.close();
|
|
return false;
|
|
}
|
|
let { activeParameter, activeSignature, signatures } = signatureHelp;
|
|
if (activeSignature) {
|
|
// make active first
|
|
let [active] = signatures.splice(activeSignature, 1);
|
|
if (active)
|
|
signatures.unshift(active);
|
|
}
|
|
if (this.preferences.signatureHelpTarget == 'float') {
|
|
let paramDoc = null;
|
|
let docs = signatures.reduce((p, c, idx) => {
|
|
let activeIndexes = null;
|
|
let nameIndex = c.label.indexOf('(');
|
|
if (idx == 0 && activeParameter != null) {
|
|
let active = c.parameters[activeParameter];
|
|
if (active) {
|
|
let after = c.label.slice(nameIndex == -1 ? 0 : nameIndex);
|
|
paramDoc = active.documentation;
|
|
if (typeof active.label === 'string') {
|
|
let str = after.slice(0);
|
|
let ms = str.match(new RegExp('\\b' + active.label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\b'));
|
|
let index = ms ? ms.index : str.indexOf(active.label);
|
|
if (index != -1) {
|
|
activeIndexes = [
|
|
index + nameIndex,
|
|
index + active.label.length + nameIndex
|
|
];
|
|
}
|
|
}
|
|
else {
|
|
activeIndexes = active.label;
|
|
}
|
|
}
|
|
}
|
|
if (activeIndexes == null) {
|
|
activeIndexes = [nameIndex + 1, nameIndex + 1];
|
|
}
|
|
p.push({
|
|
content: c.label,
|
|
filetype: document.filetype,
|
|
active: activeIndexes
|
|
});
|
|
if (paramDoc) {
|
|
let content = typeof paramDoc === 'string' ? paramDoc : paramDoc.value;
|
|
if (content.trim().length) {
|
|
p.push({
|
|
content,
|
|
filetype: vscode_languageserver_protocol_1.MarkupContent.is(c.documentation) ? 'markdown' : 'txt'
|
|
});
|
|
}
|
|
}
|
|
if (idx == 0 && c.documentation) {
|
|
let { documentation } = c;
|
|
let content = typeof documentation === 'string' ? documentation : documentation.value;
|
|
if (content.trim().length) {
|
|
p.push({
|
|
content,
|
|
filetype: vscode_languageserver_protocol_1.MarkupContent.is(c.documentation) ? 'markdown' : 'txt'
|
|
});
|
|
}
|
|
}
|
|
return p;
|
|
}, []);
|
|
let offset = 0;
|
|
let session = manager_3.default.getSession(document.bufnr);
|
|
if (session && session.isActive) {
|
|
let { value } = session.placeholder;
|
|
if (value.indexOf('\n') == -1)
|
|
offset = value.length;
|
|
}
|
|
this.signaturePosition = position;
|
|
await this.signatureFactory.create(docs, true, offset);
|
|
// show float
|
|
}
|
|
else {
|
|
let columns = workspace_1.default.env.columns;
|
|
signatures = signatures.slice(0, workspace_1.default.env.cmdheight);
|
|
let signatureList = [];
|
|
for (let signature of signatures) {
|
|
let parts = [];
|
|
let { label } = signature;
|
|
label = label.replace(/\n/g, ' ');
|
|
if (label.length >= columns - 16) {
|
|
label = label.slice(0, columns - 16) + '...';
|
|
}
|
|
let nameIndex = label.indexOf('(');
|
|
if (nameIndex == -1) {
|
|
parts = [{ text: label, type: 'Normal' }];
|
|
}
|
|
else {
|
|
parts.push({
|
|
text: label.slice(0, nameIndex),
|
|
type: 'Label'
|
|
});
|
|
let after = label.slice(nameIndex);
|
|
if (signatureList.length == 0 && activeParameter != null) {
|
|
let active = signature.parameters[activeParameter];
|
|
if (active) {
|
|
let start;
|
|
let end;
|
|
if (typeof active.label === 'string') {
|
|
let str = after.slice(0);
|
|
let ms = str.match(new RegExp('\\b' + active.label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\b'));
|
|
let idx = ms ? ms.index : str.indexOf(active.label);
|
|
if (idx == -1) {
|
|
parts.push({ text: after, type: 'Normal' });
|
|
}
|
|
else {
|
|
start = idx;
|
|
end = idx + active.label.length;
|
|
}
|
|
}
|
|
else {
|
|
[start, end] = active.label;
|
|
start = start - nameIndex;
|
|
end = end - nameIndex;
|
|
}
|
|
if (start != null && end != null) {
|
|
parts.push({ text: after.slice(0, start), type: 'Normal' });
|
|
parts.push({ text: after.slice(start, end), type: 'MoreMsg' });
|
|
parts.push({ text: after.slice(end), type: 'Normal' });
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
parts.push({
|
|
text: after,
|
|
type: 'Normal'
|
|
});
|
|
}
|
|
}
|
|
signatureList.push(parts);
|
|
}
|
|
this.nvim.callTimer('coc#util#echo_signatures', [signatureList], true);
|
|
}
|
|
return true;
|
|
}
|
|
async showSignatureHelp() {
|
|
let buffer = await this.nvim.buffer;
|
|
let document = workspace_1.default.getDocument(buffer.id);
|
|
if (!document)
|
|
return false;
|
|
let position = await workspace_1.default.getCursorPosition();
|
|
return await this.triggerSignatureHelp(document, position);
|
|
}
|
|
async handleLocations(definition, openCommand) {
|
|
if (!definition)
|
|
return;
|
|
let locations = Array.isArray(definition) ? definition : [definition];
|
|
let len = locations.length;
|
|
if (len == 0)
|
|
return;
|
|
if (len == 1 && openCommand !== false) {
|
|
let location = definition[0];
|
|
if (vscode_languageserver_protocol_1.LocationLink.is(definition[0])) {
|
|
let link = definition[0];
|
|
location = vscode_languageserver_protocol_1.Location.create(link.targetUri, link.targetRange);
|
|
}
|
|
let { uri, range } = location;
|
|
await workspace_1.default.jumpTo(uri, range.start, openCommand);
|
|
}
|
|
else {
|
|
await workspace_1.default.showLocations(definition);
|
|
}
|
|
}
|
|
async getSelectionRanges() {
|
|
let { document, position } = await workspace_1.default.getCurrentState();
|
|
let selectionRanges = await languages_1.default.getSelectionRanges(document, [position]);
|
|
if (selectionRanges && selectionRanges.length)
|
|
return selectionRanges;
|
|
return null;
|
|
}
|
|
async selectRange(visualmode, forward) {
|
|
let { nvim } = this;
|
|
let positions = [];
|
|
let bufnr = await nvim.call('bufnr', '%');
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return;
|
|
if (!forward && (!this.selectionRange || !visualmode))
|
|
return;
|
|
if (visualmode) {
|
|
let range = await workspace_1.default.getSelectedRange(visualmode, doc);
|
|
positions.push(range.start, range.end);
|
|
}
|
|
else {
|
|
let position = await workspace_1.default.getCursorPosition();
|
|
positions.push(position);
|
|
}
|
|
if (!forward) {
|
|
let curr = vscode_languageserver_protocol_1.Range.create(positions[0], positions[1]);
|
|
let { selectionRange } = this;
|
|
while (selectionRange && selectionRange.parent) {
|
|
if (object_1.equals(selectionRange.parent.range, curr)) {
|
|
break;
|
|
}
|
|
selectionRange = selectionRange.parent;
|
|
}
|
|
if (selectionRange && selectionRange.parent) {
|
|
await workspace_1.default.selectRange(selectionRange.range);
|
|
}
|
|
return;
|
|
}
|
|
let selectionRanges = await languages_1.default.getSelectionRanges(doc.textDocument, positions);
|
|
if (selectionRanges == null) {
|
|
workspace_1.default.showMessage('Selection range provider not found for current document', 'warning');
|
|
return;
|
|
}
|
|
if (!selectionRanges || selectionRanges.length == 0) {
|
|
workspace_1.default.showMessage('No selection range found', 'warning');
|
|
return;
|
|
}
|
|
let mode = await nvim.eval('mode()');
|
|
if (mode != 'n')
|
|
await nvim.eval(`feedkeys("\\<Esc>", 'in')`);
|
|
let selectionRange;
|
|
if (selectionRanges.length == 1) {
|
|
selectionRange = selectionRanges[0];
|
|
}
|
|
else if (positions.length > 1) {
|
|
let r = vscode_languageserver_protocol_1.Range.create(positions[0], positions[1]);
|
|
selectionRange = selectionRanges[0];
|
|
while (selectionRange) {
|
|
if (object_1.equals(r, selectionRange.range)) {
|
|
selectionRange = selectionRange.parent;
|
|
continue;
|
|
}
|
|
if (position_1.positionInRange(positions[1], selectionRange.range) == 0) {
|
|
break;
|
|
}
|
|
selectionRange = selectionRange.parent;
|
|
}
|
|
}
|
|
if (!selectionRange)
|
|
return;
|
|
this.selectionRange = selectionRanges[0];
|
|
await workspace_1.default.selectRange(selectionRange.range);
|
|
}
|
|
async codeActionRange(start, end, only) {
|
|
let listArgs = ['--normal', '--number-select', 'actions', `-start`, start + '', `-end`, end + ''];
|
|
if (only == 'quickfix') {
|
|
listArgs.push('-quickfix');
|
|
}
|
|
else if (only == 'source') {
|
|
listArgs.push('-source');
|
|
}
|
|
await manager_2.default.start(listArgs);
|
|
}
|
|
/**
|
|
* Refactor of current symbol
|
|
*/
|
|
async doRefactor() {
|
|
let [bufnr, cursor, filetype] = await this.nvim.eval('[bufnr("%"),coc#util#cursor(),&filetype]');
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return;
|
|
let position = { line: cursor[0], character: cursor[1] };
|
|
let res = await languages_1.default.prepareRename(doc.textDocument, position);
|
|
if (res === false) {
|
|
workspace_1.default.showMessage('Invalid position for rename', 'error');
|
|
return;
|
|
}
|
|
let edit = await languages_1.default.provideRenameEdits(doc.textDocument, position, 'newname');
|
|
if (!edit) {
|
|
workspace_1.default.showMessage('Empty workspaceEdit from server', 'warning');
|
|
return;
|
|
}
|
|
let refactor = await refactor_1.default.createFromWorkspaceEdit(edit, filetype);
|
|
if (!refactor.buffer)
|
|
return;
|
|
this.refactorMap.set(refactor.buffer.id, refactor);
|
|
}
|
|
async saveRefactor(bufnr) {
|
|
let refactor = this.refactorMap.get(bufnr);
|
|
if (refactor) {
|
|
await refactor.saveRefactor();
|
|
}
|
|
}
|
|
async search(args) {
|
|
let cwd = await this.nvim.call('getcwd');
|
|
let refactor = new refactor_1.default();
|
|
await refactor.createRefactorBuffer();
|
|
if (!refactor.buffer)
|
|
return;
|
|
this.refactorMap.set(refactor.buffer.id, refactor);
|
|
let search = new search_1.default(this.nvim);
|
|
search.run(args, cwd, refactor).logError();
|
|
}
|
|
async previewHover(hovers) {
|
|
let lines = [];
|
|
let target = this.preferences.hoverTarget;
|
|
let i = 0;
|
|
let docs = [];
|
|
for (let hover of hovers) {
|
|
let { contents } = hover;
|
|
if (i > 0)
|
|
lines.push('---');
|
|
if (Array.isArray(contents)) {
|
|
for (let item of contents) {
|
|
if (typeof item === 'string') {
|
|
if (item.trim().length) {
|
|
lines.push(...item.split('\n'));
|
|
docs.push({ content: item, filetype: 'markdown' });
|
|
}
|
|
}
|
|
else {
|
|
let content = item.value.trim();
|
|
if (target == 'preview') {
|
|
content = '``` ' + item.language + '\n' + content + '\n```';
|
|
}
|
|
lines.push(...content.trim().split('\n'));
|
|
docs.push({ filetype: item.language, content: item.value });
|
|
}
|
|
}
|
|
}
|
|
else if (typeof contents == 'string') {
|
|
lines.push(...contents.split('\n'));
|
|
docs.push({ content: contents, filetype: 'markdown' });
|
|
}
|
|
else if (vscode_languageserver_protocol_1.MarkedString.is(contents)) { // tslint:disable-line
|
|
let content = contents.value.trim();
|
|
if (target == 'preview') {
|
|
content = '``` ' + contents.language + '\n' + content + '\n```';
|
|
}
|
|
lines.push(...content.split('\n'));
|
|
docs.push({ filetype: contents.language, content: contents.value });
|
|
}
|
|
else if (vscode_languageserver_protocol_1.MarkupContent.is(contents)) {
|
|
lines.push(...contents.value.split('\n'));
|
|
docs.push({ filetype: contents.kind == 'markdown' ? 'markdown' : 'txt', content: contents.value });
|
|
}
|
|
i++;
|
|
}
|
|
if (target == 'echo') {
|
|
const msg = lines.join('\n').trim();
|
|
if (msg.length) {
|
|
await this.nvim.call('coc#util#echo_hover', msg);
|
|
}
|
|
}
|
|
else if (target == 'float') {
|
|
manager_1.default.hideFloat();
|
|
await this.hoverFactory.create(docs);
|
|
}
|
|
else {
|
|
this.documentLines = lines;
|
|
let arr = await this.nvim.call('getcurpos');
|
|
this.hoverPosition = [workspace_1.default.bufnr, arr[1], arr[2]];
|
|
await this.nvim.command(`pedit coc://document`);
|
|
}
|
|
}
|
|
getPreferences() {
|
|
let config = workspace_1.default.getConfiguration('coc.preferences');
|
|
let signatureConfig = workspace_1.default.getConfiguration('signature');
|
|
let hoverTarget = config.get('hoverTarget', 'float');
|
|
if (hoverTarget == 'float' && !workspace_1.default.env.floating && !workspace_1.default.env.textprop) {
|
|
hoverTarget = 'preview';
|
|
}
|
|
let signatureHelpTarget = signatureConfig.get('target', 'float');
|
|
if (signatureHelpTarget == 'float' && !workspace_1.default.env.floating && !workspace_1.default.env.textprop) {
|
|
signatureHelpTarget = 'echo';
|
|
}
|
|
this.labels = workspace_1.default.getConfiguration('suggest').get('completionItemKindLabels', {});
|
|
this.preferences = {
|
|
hoverTarget,
|
|
signatureHelpTarget,
|
|
signatureMaxHeight: signatureConfig.get('maxWindowHeight', 8),
|
|
triggerSignatureHelp: signatureConfig.get('enable', true),
|
|
triggerSignatureWait: signatureConfig.get('triggerSignatureWait', 50),
|
|
signaturePreferAbove: signatureConfig.get('preferShownAbove', true),
|
|
signatureFloatMaxWidth: signatureConfig.get('floatMaxWidth', 80),
|
|
signatureHideOnChange: signatureConfig.get('hideOnTextChange', false),
|
|
formatOnType: config.get('formatOnType', false),
|
|
bracketEnterImprove: config.get('bracketEnterImprove', true),
|
|
previewAutoClose: config.get('previewAutoClose', false),
|
|
currentFunctionSymbolAutoUpdate: config.get('currentFunctionSymbolAutoUpdate', false),
|
|
};
|
|
}
|
|
onEmptyLocation(name, location) {
|
|
if (location == null) {
|
|
workspace_1.default.showMessage(`${name} provider not found for current document`, 'warning');
|
|
}
|
|
else if (location.length == 0) {
|
|
workspace_1.default.showMessage(`${name} not found`, 'warning');
|
|
}
|
|
}
|
|
dispose() {
|
|
this.colors.dispose();
|
|
util_1.disposeAll(this.disposables);
|
|
}
|
|
}
|
|
exports.default = Handler;
|
|
function getPreviousContainer(containerName, symbols) {
|
|
if (!symbols.length)
|
|
return null;
|
|
let i = symbols.length - 1;
|
|
let last = symbols[i];
|
|
if (last.text == containerName) {
|
|
return last;
|
|
}
|
|
while (i >= 0) {
|
|
let sym = symbols[i];
|
|
if (sym.text == containerName) {
|
|
return sym;
|
|
}
|
|
i--;
|
|
}
|
|
return null;
|
|
}
|
|
function sortDocumentSymbols(a, b) {
|
|
let ra = a.selectionRange;
|
|
let rb = b.selectionRange;
|
|
if (ra.start.line < rb.start.line) {
|
|
return -1;
|
|
}
|
|
if (ra.start.line > rb.start.line) {
|
|
return 1;
|
|
}
|
|
return ra.start.character - rb.start.character;
|
|
}
|
|
function addDoucmentSymbol(res, sym, level) {
|
|
let { name, selectionRange, kind, children, range } = sym;
|
|
let { start } = selectionRange;
|
|
res.push({
|
|
col: start.character + 1,
|
|
lnum: start.line + 1,
|
|
text: name,
|
|
level,
|
|
kind: convert_1.getSymbolKind(kind),
|
|
range,
|
|
selectionRange
|
|
});
|
|
if (children && children.length) {
|
|
children.sort(sortDocumentSymbols);
|
|
for (let sym of children) {
|
|
addDoucmentSymbol(res, sym, level + 1);
|
|
}
|
|
}
|
|
}
|
|
function sortSymbolInformations(a, b) {
|
|
let sa = a.location.range.start;
|
|
let sb = b.location.range.start;
|
|
let d = sa.line - sb.line;
|
|
return d == 0 ? sa.character - sb.character : d;
|
|
}
|
|
function isDocumentSymbol(a) {
|
|
return a && !a.hasOwnProperty('location');
|
|
}
|
|
function isEmpty(location) {
|
|
if (!location)
|
|
return true;
|
|
if (Array.isArray(location) && location.length == 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
function isDocumentSymbols(a) {
|
|
return isDocumentSymbol(a[0]);
|
|
}
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
/* 400 */
|
|
/***/ (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__(176));
|
|
const commands_1 = tslib_1.__importDefault(__webpack_require__(232));
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const languages_1 = tslib_1.__importDefault(__webpack_require__(315));
|
|
const services_1 = tslib_1.__importDefault(__webpack_require__(351));
|
|
const util_1 = __webpack_require__(174);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('codelens');
|
|
class CodeLensManager {
|
|
constructor(nvim) {
|
|
this.nvim = nvim;
|
|
this.fetching = new Set();
|
|
this.disposables = [];
|
|
this.codeLensMap = new Map();
|
|
this.init().catch(e => {
|
|
logger.error(e.message);
|
|
});
|
|
}
|
|
async init() {
|
|
this.setConfiguration();
|
|
if (!this.enabled)
|
|
return;
|
|
this.srcId = workspace_1.default.createNameSpace('coc-codelens') || 1080;
|
|
services_1.default.on('ready', async (id) => {
|
|
let service = services_1.default.getService(id);
|
|
let doc = workspace_1.default.getDocument(workspace_1.default.bufnr);
|
|
if (!doc)
|
|
return;
|
|
if (workspace_1.default.match(service.selector, doc.textDocument)) {
|
|
this.resolveCodeLens.clear();
|
|
await util_1.wait(2000);
|
|
await this.fetchDocumentCodeLenes();
|
|
}
|
|
});
|
|
let timer;
|
|
workspace_1.default.onDidChangeTextDocument(async (e) => {
|
|
let doc = workspace_1.default.getDocument(e.textDocument.uri);
|
|
if (doc && doc.bufnr == workspace_1.default.bufnr) {
|
|
if (timer)
|
|
clearTimeout(timer);
|
|
setTimeout(async () => {
|
|
await this.fetchDocumentCodeLenes();
|
|
}, 100);
|
|
}
|
|
}, null, this.disposables);
|
|
workspace_1.default.onDidChangeConfiguration(e => {
|
|
if (e.affectsConfiguration('codelens')) {
|
|
this.setConfiguration();
|
|
}
|
|
}, null, this.disposables);
|
|
events_1.default.on(['TextChanged', 'TextChangedI'], async () => {
|
|
this.resolveCodeLens.clear();
|
|
}, null, this.disposables);
|
|
events_1.default.on('CursorMoved', () => {
|
|
this.resolveCodeLens();
|
|
}, null, this.disposables);
|
|
events_1.default.on('BufUnload', bufnr => {
|
|
let buf = this.nvim.createBuffer(bufnr);
|
|
if (this.nvim.hasFunction('nvim_create_namespace')) {
|
|
buf.clearNamespace(this.srcId);
|
|
}
|
|
else {
|
|
buf.clearHighlight({ srcId: this.srcId });
|
|
}
|
|
}, null, this.disposables);
|
|
events_1.default.on('BufEnter', bufnr => {
|
|
setTimeout(async () => {
|
|
if (workspace_1.default.bufnr == bufnr) {
|
|
await this.fetchDocumentCodeLenes();
|
|
}
|
|
}, 100);
|
|
}, null, this.disposables);
|
|
events_1.default.on('InsertLeave', async () => {
|
|
let { bufnr } = workspace_1.default;
|
|
let info = this.codeLensMap.get(bufnr);
|
|
if (info && info.version != this.version) {
|
|
this.resolveCodeLens.clear();
|
|
await util_1.wait(50);
|
|
await this.fetchDocumentCodeLenes();
|
|
}
|
|
}, null, this.disposables);
|
|
this.resolveCodeLens = debounce_1.default(() => {
|
|
this._resolveCodeLenes().catch(e => {
|
|
logger.error(e);
|
|
});
|
|
}, 200);
|
|
}
|
|
setConfiguration() {
|
|
let { nvim } = this;
|
|
let config = workspace_1.default.getConfiguration('coc.preferences.codeLens');
|
|
if (Object.keys(config).length == 0) {
|
|
config = workspace_1.default.getConfiguration('codeLens');
|
|
}
|
|
this.separator = config.get('separator', '‣');
|
|
this.enabled = nvim.hasFunction('nvim_buf_set_virtual_text') && config.get('enable', true);
|
|
}
|
|
async fetchDocumentCodeLenes(retry = 0) {
|
|
let doc = workspace_1.default.getDocument(workspace_1.default.bufnr);
|
|
if (!doc)
|
|
return;
|
|
let { uri, version, bufnr } = doc;
|
|
let document = workspace_1.default.getDocument(uri);
|
|
if (!this.validDocument(document))
|
|
return;
|
|
if (this.fetching.has(bufnr))
|
|
return;
|
|
this.fetching.add(bufnr);
|
|
try {
|
|
let codeLenes = await languages_1.default.getCodeLens(document.textDocument);
|
|
if (codeLenes && codeLenes.length > 0) {
|
|
this.codeLensMap.set(document.bufnr, { codeLenes, version });
|
|
if (workspace_1.default.bufnr == document.bufnr) {
|
|
this.resolveCodeLens.clear();
|
|
await this._resolveCodeLenes(true);
|
|
}
|
|
}
|
|
this.fetching.delete(bufnr);
|
|
}
|
|
catch (e) {
|
|
this.fetching.delete(bufnr);
|
|
logger.error(e);
|
|
if (/timeout/.test(e.message) && retry < 5) {
|
|
this.fetchDocumentCodeLenes(retry + 1); // tslint:disable-line
|
|
}
|
|
}
|
|
}
|
|
async setVirtualText(buffer, codeLenes) {
|
|
let list = new Map();
|
|
for (let codeLens of codeLenes) {
|
|
let { range, command } = codeLens;
|
|
if (!command)
|
|
continue;
|
|
let { line } = range.start;
|
|
if (list.has(line)) {
|
|
list.get(line).push(codeLens);
|
|
}
|
|
else {
|
|
list.set(line, [codeLens]);
|
|
}
|
|
}
|
|
for (let lnum of list.keys()) {
|
|
let codeLenes = list.get(lnum);
|
|
let commands = codeLenes.map(codeLens => codeLens.command);
|
|
commands = commands.filter(c => c && c.title);
|
|
let chunks = commands.map(c => [c.title + ' ', 'CocCodeLens']);
|
|
chunks.unshift([`${this.separator} `, 'CocCodeLens']);
|
|
await buffer.setVirtualText(this.srcId, lnum, chunks);
|
|
}
|
|
}
|
|
async _resolveCodeLenes(clear = false) {
|
|
let { nvim } = this;
|
|
let { bufnr } = workspace_1.default;
|
|
let { codeLenes, version } = this.codeLensMap.get(bufnr) || {};
|
|
if (workspace_1.default.insertMode)
|
|
return;
|
|
if (codeLenes && codeLenes.length) {
|
|
// resolve codeLens of current window
|
|
let start = await nvim.call('line', 'w0');
|
|
let end = await nvim.call('line', 'w$');
|
|
if (version && this.version != version)
|
|
return;
|
|
if (end >= start) {
|
|
codeLenes = codeLenes.filter(o => {
|
|
let lnum = o.range.start.line + 1;
|
|
return lnum >= start && lnum <= end;
|
|
});
|
|
if (codeLenes.length) {
|
|
await Promise.all(codeLenes.map(codeLens => {
|
|
return languages_1.default.resolveCodeLens(codeLens);
|
|
}));
|
|
}
|
|
}
|
|
else {
|
|
codeLenes = null;
|
|
}
|
|
}
|
|
nvim.pauseNotification();
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (doc && clear) {
|
|
doc.clearMatchIds([this.srcId]);
|
|
}
|
|
if (codeLenes && codeLenes.length)
|
|
await this.setVirtualText(doc.buffer, codeLenes);
|
|
nvim.resumeNotification().catch(_e => {
|
|
// noop
|
|
});
|
|
}
|
|
async doAction() {
|
|
let { nvim } = this;
|
|
let bufnr = await nvim.call('bufnr', '%');
|
|
let line = await nvim.call('line', '.') - 1;
|
|
let { codeLenes } = this.codeLensMap.get(bufnr);
|
|
if (!codeLenes || codeLenes.length == 0) {
|
|
workspace_1.default.showMessage('No codeLenes available', 'warning');
|
|
return;
|
|
}
|
|
let list = new Map();
|
|
for (let codeLens of codeLenes) {
|
|
let { range, command } = codeLens;
|
|
if (!command)
|
|
continue;
|
|
let { line } = range.start;
|
|
if (list.has(line)) {
|
|
list.get(line).push(codeLens);
|
|
}
|
|
else {
|
|
list.set(line, [codeLens]);
|
|
}
|
|
}
|
|
let current = null;
|
|
for (let i = line; i >= 0; i--) {
|
|
if (list.has(i)) {
|
|
current = list.get(i);
|
|
break;
|
|
}
|
|
}
|
|
if (!current) {
|
|
workspace_1.default.showMessage('No codeLenes available', 'warning');
|
|
return;
|
|
}
|
|
let commands = current.map(o => o.command);
|
|
commands = commands.filter(c => c.command != null && c.command != '');
|
|
if (commands.length == 0) {
|
|
workspace_1.default.showMessage('CodeLenes command not found', 'warning');
|
|
}
|
|
else if (commands.length == 1) {
|
|
commands_1.default.execute(commands[0]);
|
|
}
|
|
else {
|
|
let res = await workspace_1.default.showQuickpick(commands.map(c => c.title));
|
|
if (res == -1)
|
|
return;
|
|
commands_1.default.execute(commands[res]);
|
|
}
|
|
}
|
|
validDocument(doc) {
|
|
if (!doc)
|
|
return false;
|
|
if (doc.schema != 'file' || doc.buftype != '')
|
|
return false;
|
|
return true;
|
|
}
|
|
get version() {
|
|
let doc = workspace_1.default.getDocument(workspace_1.default.bufnr);
|
|
return doc ? doc.version : 0;
|
|
}
|
|
dispose() {
|
|
if (this.resolveCodeLens) {
|
|
this.resolveCodeLens.clear();
|
|
}
|
|
util_1.disposeAll(this.disposables);
|
|
}
|
|
}
|
|
exports.default = CodeLensManager;
|
|
//# sourceMappingURL=codelens.js.map
|
|
|
|
/***/ }),
|
|
/* 401 */
|
|
/***/ (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__(176));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const languages_1 = tslib_1.__importDefault(__webpack_require__(315));
|
|
const util_1 = __webpack_require__(174);
|
|
const object_1 = __webpack_require__(190);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const highlighter_1 = tslib_1.__importStar(__webpack_require__(402));
|
|
const logger = __webpack_require__(186)('colors');
|
|
class Colors {
|
|
constructor(nvim) {
|
|
this.nvim = nvim;
|
|
this._enabled = true;
|
|
this.srcId = 1090;
|
|
this.disposables = [];
|
|
this.highlighters = new Map();
|
|
this.highlightCurrent = debounce_1.default(() => {
|
|
this._highlightCurrent().catch(e => {
|
|
logger.error('highlight error:', e.stack);
|
|
});
|
|
}, 200);
|
|
let config = workspace_1.default.getConfiguration('coc.preferences');
|
|
this._enabled = config.get('colorSupport', true);
|
|
this.srcId = workspace_1.default.createNameSpace('coc-colors');
|
|
let timer = setTimeout(async () => {
|
|
// wait for extensions
|
|
await this._highlightCurrent();
|
|
}, 2000);
|
|
this.disposables.push(vscode_languageserver_protocol_1.Disposable.create(() => {
|
|
clearTimeout(timer);
|
|
}));
|
|
events_1.default.on('BufEnter', async () => {
|
|
if (global.hasOwnProperty('__TEST__'))
|
|
return;
|
|
this.highlightCurrent();
|
|
}, null, this.disposables);
|
|
events_1.default.on('InsertLeave', async () => {
|
|
this.highlightCurrent();
|
|
}, null, this.disposables);
|
|
events_1.default.on('BufUnload', async (bufnr) => {
|
|
let highlighter = this.highlighters.get(bufnr);
|
|
if (highlighter) {
|
|
highlighter.dispose();
|
|
this.highlighters.delete(bufnr);
|
|
}
|
|
}, null, this.disposables);
|
|
workspace_1.default.onDidChangeTextDocument(async ({ textDocument, contentChanges }) => {
|
|
if (workspace_1.default.insertMode)
|
|
return;
|
|
let doc = workspace_1.default.getDocument(textDocument.uri);
|
|
if (doc && doc.bufnr == workspace_1.default.bufnr) {
|
|
let { range, text } = contentChanges[0];
|
|
await util_1.wait(50);
|
|
await this.highlightColors(doc);
|
|
}
|
|
}, null, this.disposables);
|
|
workspace_1.default.onDidChangeConfiguration(async (e) => {
|
|
if (e.affectsConfiguration('coc.preferences.colorSupport')) {
|
|
let config = workspace_1.default.getConfiguration('coc.preferences');
|
|
this._enabled = config.get('colorSupport', true);
|
|
}
|
|
}, null, this.disposables);
|
|
}
|
|
async _highlightCurrent() {
|
|
if (!this.enabled)
|
|
return;
|
|
let { bufnr } = workspace_1.default;
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (doc)
|
|
await this.highlightColors(doc);
|
|
}
|
|
async highlightColors(document, force = false) {
|
|
if (!this.enabled)
|
|
return;
|
|
if (['help', 'terminal', 'quickfix'].indexOf(document.buftype) !== -1)
|
|
return;
|
|
let { version, changedtick } = document;
|
|
let highlighter = this.getHighlighter(document.bufnr);
|
|
if (!highlighter || (highlighter.version == version && !force))
|
|
return;
|
|
let colors;
|
|
try {
|
|
colors = await languages_1.default.provideDocumentColors(document.textDocument);
|
|
colors = colors || [];
|
|
if (changedtick != document.changedtick)
|
|
return;
|
|
if (!force && object_1.equals(highlighter.colors, colors))
|
|
return;
|
|
await highlighter.highlight(colors);
|
|
}
|
|
catch (e) {
|
|
logger.error(e.stack);
|
|
}
|
|
}
|
|
async pickPresentation() {
|
|
let info = await this.currentColorInfomation();
|
|
if (!info)
|
|
return workspace_1.default.showMessage('Color not found at current position', 'warning');
|
|
let document = await workspace_1.default.document;
|
|
let presentations = await languages_1.default.provideColorPresentations(info, document.textDocument);
|
|
if (!presentations || presentations.length == 0)
|
|
return;
|
|
let res = await workspace_1.default.showQuickpick(presentations.map(o => o.label), 'choose a color presentation:');
|
|
if (res == -1)
|
|
return;
|
|
let presentation = presentations[res];
|
|
let { textEdit, additionalTextEdits, label } = presentation;
|
|
if (!textEdit)
|
|
textEdit = { range: info.range, newText: label };
|
|
await document.applyEdits(this.nvim, [textEdit]);
|
|
if (additionalTextEdits) {
|
|
await document.applyEdits(this.nvim, additionalTextEdits);
|
|
}
|
|
}
|
|
async pickColor() {
|
|
let info = await this.currentColorInfomation();
|
|
if (!info)
|
|
return workspace_1.default.showMessage('Color not found at current position', 'warning');
|
|
let { color } = info;
|
|
let colorArr = [(color.red * 255).toFixed(0), (color.green * 255).toFixed(0), (color.blue * 255).toFixed(0)];
|
|
let res = await this.nvim.call('coc#util#pick_color', [colorArr]);
|
|
if (res === false) {
|
|
// cancel
|
|
return;
|
|
}
|
|
if (!res || res.length != 3) {
|
|
workspace_1.default.showMessage('Failed to get color', 'warning');
|
|
return;
|
|
}
|
|
let hex = highlighter_1.toHexString({
|
|
red: (res[0] / 65535),
|
|
green: (res[1] / 65535),
|
|
blue: (res[2] / 65535),
|
|
alpha: 1
|
|
});
|
|
let document = await workspace_1.default.document;
|
|
await document.applyEdits(this.nvim, [{
|
|
range: info.range,
|
|
newText: `#${hex}`
|
|
}]);
|
|
}
|
|
get enabled() {
|
|
return this._enabled;
|
|
}
|
|
clearHighlight(bufnr) {
|
|
let highlighter = this.highlighters.get(bufnr);
|
|
if (!highlighter)
|
|
return;
|
|
highlighter.clearHighlight();
|
|
}
|
|
hasColor(bufnr) {
|
|
let highlighter = this.highlighters.get(bufnr);
|
|
if (!highlighter)
|
|
return false;
|
|
return highlighter.hasColor();
|
|
}
|
|
hasColorAtPostion(bufnr, position) {
|
|
let highlighter = this.highlighters.get(bufnr);
|
|
if (!highlighter)
|
|
return false;
|
|
return highlighter.hasColorAtPostion(position);
|
|
}
|
|
dispose() {
|
|
this.highlightCurrent.clear();
|
|
for (let highlighter of this.highlighters.values()) {
|
|
highlighter.dispose();
|
|
}
|
|
util_1.disposeAll(this.disposables);
|
|
}
|
|
getHighlighter(bufnr) {
|
|
let obj = this.highlighters.get(bufnr);
|
|
if (obj)
|
|
return obj;
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return null;
|
|
obj = new highlighter_1.default(this.nvim, doc, this.srcId);
|
|
this.highlighters.set(bufnr, obj);
|
|
return obj;
|
|
}
|
|
async currentColorInfomation() {
|
|
let bufnr = await this.nvim.call('bufnr', '%');
|
|
let highlighter = this.highlighters.get(bufnr);
|
|
if (!highlighter)
|
|
return;
|
|
let position = await workspace_1.default.getCursorPosition();
|
|
for (let info of highlighter.colors) {
|
|
let { range } = info;
|
|
let { start, end } = range;
|
|
if (position.line == start.line
|
|
&& position.character >= start.character
|
|
&& position.character <= end.character) {
|
|
return info;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
exports.default = Colors;
|
|
//# sourceMappingURL=colors.js.map
|
|
|
|
/***/ }),
|
|
/* 402 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const array_1 = __webpack_require__(212);
|
|
const object_1 = __webpack_require__(190);
|
|
const position_1 = __webpack_require__(213);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('highlighter');
|
|
const usedColors = new Set();
|
|
class Highlighter {
|
|
constructor(nvim, document, srcId) {
|
|
this.nvim = nvim;
|
|
this.document = document;
|
|
this.srcId = srcId;
|
|
this.matchIds = new Set();
|
|
this._colors = [];
|
|
}
|
|
get version() {
|
|
return this._version;
|
|
}
|
|
get bufnr() {
|
|
return this.document.bufnr;
|
|
}
|
|
get colors() {
|
|
return this._colors;
|
|
}
|
|
hasColor() {
|
|
return this._colors.length > 0;
|
|
}
|
|
async highlight(colors) {
|
|
colors = colors || [];
|
|
this._version = this.document.version;
|
|
if (workspace_1.default.isVim
|
|
&& !workspace_1.default.env.textprop
|
|
&& workspace_1.default.bufnr != this.document.bufnr)
|
|
return;
|
|
if (colors.length == 0)
|
|
return this.clearHighlight();
|
|
this._colors = colors;
|
|
let groups = array_1.group(colors, 100);
|
|
let cleared = false;
|
|
for (let colors of groups) {
|
|
this.nvim.pauseNotification();
|
|
if (!cleared) {
|
|
cleared = true;
|
|
this.document.clearMatchIds(this.matchIds);
|
|
this.matchIds.clear();
|
|
}
|
|
let colorRanges = this.getColorRanges(colors);
|
|
this.addColors(colors.map(o => o.color));
|
|
for (let o of colorRanges) {
|
|
this.addHighlight(o.ranges, o.color);
|
|
}
|
|
this.nvim.command('redraw', true);
|
|
await this.nvim.resumeNotification();
|
|
}
|
|
}
|
|
addHighlight(ranges, color) {
|
|
let { red, green, blue } = toHexColor(color);
|
|
let hlGroup = `BG${toHexString(color)}`;
|
|
let ids = this.document.highlightRanges(ranges, hlGroup, this.srcId);
|
|
for (let id of ids) {
|
|
this.matchIds.add(id);
|
|
}
|
|
}
|
|
addColors(colors) {
|
|
let commands = [];
|
|
for (let color of colors) {
|
|
let hex = toHexString(color);
|
|
if (!usedColors.has(hex)) {
|
|
commands.push(`hi BG${hex} guibg=#${hex} guifg=#${isDark(color) ? 'ffffff' : '000000'}`);
|
|
usedColors.add(hex);
|
|
}
|
|
}
|
|
this.nvim.command(commands.join('|'), true);
|
|
}
|
|
clearHighlight() {
|
|
let { matchIds } = this;
|
|
if (!this.document)
|
|
return;
|
|
this.matchIds.clear();
|
|
this.document.clearMatchIds(matchIds);
|
|
this._colors = [];
|
|
}
|
|
getColorRanges(infos) {
|
|
let res = [];
|
|
for (let info of infos) {
|
|
let { color, range } = info;
|
|
let idx = res.findIndex(o => {
|
|
return object_1.equals(toHexColor(o.color), toHexColor(color));
|
|
});
|
|
if (idx == -1) {
|
|
res.push({
|
|
color,
|
|
ranges: [range]
|
|
});
|
|
}
|
|
else {
|
|
let r = res[idx];
|
|
r.ranges.push(range);
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
hasColorAtPostion(position) {
|
|
let { colors } = this;
|
|
return colors.some(o => position_1.positionInRange(position, o.range) == 0);
|
|
}
|
|
dispose() {
|
|
this.clearHighlight();
|
|
this.document = null;
|
|
}
|
|
}
|
|
exports.default = Highlighter;
|
|
function toHexString(color) {
|
|
let c = toHexColor(color);
|
|
return `${pad(c.red.toString(16))}${pad(c.green.toString(16))}${pad(c.blue.toString(16))}`;
|
|
}
|
|
exports.toHexString = toHexString;
|
|
function pad(str) {
|
|
return str.length == 1 ? `0${str}` : str;
|
|
}
|
|
function toHexColor(color) {
|
|
let { red, green, blue } = color;
|
|
return {
|
|
red: Math.round(red * 255),
|
|
green: Math.round(green * 255),
|
|
blue: Math.round(blue * 255)
|
|
};
|
|
}
|
|
function isDark(color) {
|
|
// http://www.w3.org/TR/WCAG20/#relativeluminancedef
|
|
let rgb = [color.red, color.green, color.blue];
|
|
let lum = [];
|
|
for (let i = 0; i < rgb.length; i++) {
|
|
let chan = rgb[i];
|
|
lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4);
|
|
}
|
|
let luma = 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2];
|
|
return luma <= 0.5;
|
|
}
|
|
//# sourceMappingURL=highlighter.js.map
|
|
|
|
/***/ }),
|
|
/* 403 */
|
|
/***/ (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__(148));
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const languages_1 = tslib_1.__importDefault(__webpack_require__(315));
|
|
const vscode_languageserver_protocol_1 = __webpack_require__(149);
|
|
const util_1 = __webpack_require__(174);
|
|
const logger = __webpack_require__(186)('documentHighlight');
|
|
class DocumentHighlighter {
|
|
constructor(nvim, colors) {
|
|
this.nvim = nvim;
|
|
this.colors = colors;
|
|
this.disposables = [];
|
|
this.matchIds = new Set();
|
|
events_1.default.on('BufWinEnter', () => {
|
|
this.clearHighlight();
|
|
}, null, this.disposables);
|
|
events_1.default.on(['CursorMoved', 'CursorMovedI'], () => {
|
|
this.cursorMoveTs = Date.now();
|
|
}, null, this.disposables);
|
|
events_1.default.on('InsertEnter', () => {
|
|
this.clearHighlight();
|
|
}, null, this.disposables);
|
|
}
|
|
// clear matchIds of current window
|
|
clearHighlight() {
|
|
let { matchIds } = this;
|
|
let { nvim } = workspace_1.default;
|
|
if (matchIds.size == 0)
|
|
return;
|
|
nvim.pauseNotification();
|
|
nvim.call('coc#util#clearmatches', [Array.from(matchIds)], true);
|
|
nvim.command('redraw', true);
|
|
nvim.resumeNotification(false, true).catch(_e => {
|
|
// noop
|
|
});
|
|
this.matchIds.clear();
|
|
}
|
|
async highlight(bufnr) {
|
|
let { nvim } = this;
|
|
let document = workspace_1.default.getDocument(bufnr);
|
|
let highlights = await this.getHighlights(document);
|
|
if (!highlights || highlights.length == 0) {
|
|
this.clearHighlight();
|
|
return;
|
|
}
|
|
if (workspace_1.default.bufnr != bufnr)
|
|
return;
|
|
nvim.pauseNotification();
|
|
this.clearHighlight();
|
|
let groups = {};
|
|
for (let hl of highlights) {
|
|
let hlGroup = hl.kind == vscode_languageserver_protocol_1.DocumentHighlightKind.Text
|
|
? 'CocHighlightText'
|
|
: hl.kind == vscode_languageserver_protocol_1.DocumentHighlightKind.Read ? 'CocHighlightRead' : 'CocHighlightWrite';
|
|
groups[hlGroup] = groups[hlGroup] || [];
|
|
groups[hlGroup].push(hl.range);
|
|
}
|
|
for (let hlGroup of Object.keys(groups)) {
|
|
let ids = document.matchAddRanges(groups[hlGroup], hlGroup, -1);
|
|
for (let id of ids) {
|
|
this.matchIds.add(id);
|
|
}
|
|
}
|
|
this.nvim.command('redraw', true);
|
|
await this.nvim.resumeNotification(false, true);
|
|
}
|
|
async getHighlights(document) {
|
|
if (!document)
|
|
return null;
|
|
let ts = Date.now();
|
|
let { bufnr } = document;
|
|
let position = await workspace_1.default.getCursorPosition();
|
|
let line = document.getline(position.line);
|
|
let ch = line[position.character];
|
|
if (!ch || !document.isWord(ch) || this.colors.hasColorAtPostion(bufnr, position))
|
|
return null;
|
|
try {
|
|
let highlights = await languages_1.default.getDocumentHighLight(document.textDocument, position);
|
|
if (workspace_1.default.bufnr != document.bufnr || (this.cursorMoveTs && this.cursorMoveTs > ts)) {
|
|
return null;
|
|
}
|
|
return highlights;
|
|
}
|
|
catch (_e) {
|
|
return null;
|
|
}
|
|
}
|
|
dispose() {
|
|
util_1.disposeAll(this.disposables);
|
|
}
|
|
}
|
|
exports.default = DocumentHighlighter;
|
|
//# sourceMappingURL=documentHighlight.js.map
|
|
|
|
/***/ }),
|
|
/* 404 */
|
|
/***/ (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__(209));
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const vscode_languageserver_types_1 = __webpack_require__(161);
|
|
const vscode_uri_1 = __webpack_require__(180);
|
|
const commands_1 = tslib_1.__importDefault(__webpack_require__(232));
|
|
const highligher_1 = tslib_1.__importDefault(__webpack_require__(349));
|
|
const util_1 = __webpack_require__(174);
|
|
const fs_1 = __webpack_require__(200);
|
|
const object_1 = __webpack_require__(190);
|
|
const string_1 = __webpack_require__(210);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('refactor');
|
|
// cases: buffer change event
|
|
const name = '__coc_refactor__';
|
|
const separator = '\u3000';
|
|
let refactorId = 0;
|
|
class Refactor {
|
|
constructor() {
|
|
this.changing = false;
|
|
this.matchIds = new Set();
|
|
this.disposables = [];
|
|
this.fileItems = [];
|
|
this.nvim = workspace_1.default.nvim;
|
|
if (workspace_1.default.isNvim && this.nvim.hasFunction('nvim_buf_set_virtual_text')) {
|
|
this.srcId = workspace_1.default.createNameSpace('coc-refactor');
|
|
}
|
|
let config = workspace_1.default.getConfiguration('refactor');
|
|
this.config = {
|
|
afterContext: config.get('afterContext', 3),
|
|
beforeContext: config.get('beforeContext', 3),
|
|
openCommand: config.get('openCommand', 'edit')
|
|
};
|
|
}
|
|
get buffer() {
|
|
if (!this.bufnr)
|
|
return null;
|
|
return this.nvim.createBuffer(this.bufnr);
|
|
}
|
|
get document() {
|
|
if (!this.bufnr)
|
|
return null;
|
|
return workspace_1.default.getDocument(this.bufnr);
|
|
}
|
|
async valid() {
|
|
let { buffer } = this;
|
|
if (!buffer)
|
|
return false;
|
|
return await buffer.valid;
|
|
}
|
|
/**
|
|
* Start refactor from workspaceEdit
|
|
*/
|
|
async fromWorkspaceEdit(edit, filetype) {
|
|
let items = await this.getItemsFromWorkspaceEdit(edit);
|
|
await this.createRefactorBuffer(filetype);
|
|
await this.addFileItems(items);
|
|
}
|
|
async fromLines(lines) {
|
|
let buf = await this.createRefactorBuffer();
|
|
await buf.setLines(lines, { start: 0, end: -1, strictIndexing: false });
|
|
}
|
|
/**
|
|
* Create initialized refactor buffer
|
|
*/
|
|
async createRefactorBuffer(filetype) {
|
|
let { nvim } = this;
|
|
let [fromWinid, cwd] = await nvim.eval('[win_getid(),getcwd()]');
|
|
let { openCommand } = this.config;
|
|
nvim.pauseNotification();
|
|
nvim.command(`${openCommand} ${name}${refactorId++}`, true);
|
|
nvim.command(`setl buftype=acwrite nobuflisted bufhidden=wipe nofen wrap conceallevel=2 concealcursor=n`, true);
|
|
nvim.command(`setl undolevels=-1 nolist nospell noswapfile foldmethod=expr foldexpr=coc#util#refactor_foldlevel(v:lnum)`, true);
|
|
nvim.command(`setl foldtext=coc#util#refactor_fold_text(v:foldstart)`, true);
|
|
nvim.call('setline', [1, ['Save current buffer to make changes', separator]], true);
|
|
nvim.call('matchadd', ['Comment', '\\%1l'], true);
|
|
nvim.call('matchadd', ['Conceal', '^\\%u3000'], true);
|
|
nvim.call('matchadd', ['Label', '^\\%u3000\\zs\\S\\+'], true);
|
|
nvim.command('setl nomod', true);
|
|
if (filetype)
|
|
nvim.command(`runtime! syntax/${filetype}.vim`, true);
|
|
nvim.call('coc#util#do_autocmd', ['CocRefactorOpen'], true);
|
|
workspace_1.default.registerLocalKeymap('n', '<CR>', this.splitOpen.bind(this), true);
|
|
let [, err] = await nvim.resumeNotification();
|
|
if (err) {
|
|
logger.error(err);
|
|
workspace_1.default.showMessage(`Error on open refactor window: ${err}`, 'error');
|
|
return;
|
|
}
|
|
let [bufnr, win] = await nvim.eval('[bufnr("%"),win_getid()]');
|
|
this.fromWinid = fromWinid;
|
|
this.winid = win;
|
|
this.bufnr = bufnr;
|
|
this.cwd = cwd;
|
|
await this.ensureDocument();
|
|
workspace_1.default.onDidChangeTextDocument(this.onBufferChange, this, this.disposables);
|
|
return nvim.createBuffer(bufnr);
|
|
}
|
|
/**
|
|
* Add FileItem to refactor buffer.
|
|
*/
|
|
async addFileItems(items) {
|
|
let { document } = this;
|
|
if (!document)
|
|
return;
|
|
if (document.dirty)
|
|
document.forceSync();
|
|
for (let item of items) {
|
|
let fileItem = this.fileItems.find(o => o.filepath == item.filepath);
|
|
if (fileItem) {
|
|
fileItem.ranges.push(...item.ranges);
|
|
}
|
|
else {
|
|
this.fileItems.push(item);
|
|
}
|
|
}
|
|
let count = document.lineCount;
|
|
let highligher = new highligher_1.default();
|
|
let hlRanges = [];
|
|
for (let item of items) {
|
|
for (let range of item.ranges) {
|
|
highligher.addLine(separator);
|
|
highligher.addLine(separator);
|
|
range.lnum = count + highligher.length;
|
|
highligher.addText(`${this.cwd && fs_1.isParentFolder(this.cwd, item.filepath) ? path_1.default.relative(this.cwd, item.filepath) : item.filepath}`);
|
|
// white spaces for conceal texts
|
|
let n = String(range.start + 1).length + String(range.end).length + 4;
|
|
if (!this.srcId)
|
|
highligher.addText(' '.repeat(n));
|
|
let base = 0 - highligher.length - count;
|
|
if (range.highlights) {
|
|
hlRanges.push(...range.highlights.map(r => adjustRange(r, base)));
|
|
}
|
|
let { lines } = range;
|
|
if (!lines) {
|
|
lines = await this.getLines(item.filepath, range.start, range.end);
|
|
range.lines = lines;
|
|
}
|
|
highligher.addLines(lines);
|
|
}
|
|
}
|
|
let { nvim, buffer } = this;
|
|
this.version = document.version;
|
|
nvim.pauseNotification();
|
|
highligher.render(buffer, count);
|
|
this.highlightLineNr();
|
|
buffer.setOption('modified', false, true);
|
|
buffer.setOption('undolevels', 1000, true);
|
|
if (count == 2 && hlRanges.length) {
|
|
let pos = hlRanges[0].start;
|
|
nvim.call('coc#util#jumpTo', [pos.line, pos.character], true);
|
|
}
|
|
let [, err] = await nvim.resumeNotification();
|
|
if (err) {
|
|
logger.error(err);
|
|
return;
|
|
}
|
|
await document._fetchContent();
|
|
document.forceSync();
|
|
await commands_1.default.executeCommand('editor.action.addRanges', hlRanges);
|
|
}
|
|
async ensureDocument() {
|
|
let { bufnr } = this;
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (doc)
|
|
return;
|
|
return new Promise((resolve, reject) => {
|
|
let timer = setTimeout(() => {
|
|
reject(new Error('Document create timeout after 2s.'));
|
|
}, 2000);
|
|
let disposable = workspace_1.default.onDidOpenTextDocument(({ uri }) => {
|
|
let doc = workspace_1.default.getDocument(uri);
|
|
if (doc.bufnr == bufnr) {
|
|
clearTimeout(timer);
|
|
disposable.dispose();
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
/**
|
|
* Use conceal to add lineNr
|
|
*/
|
|
highlightLineNr() {
|
|
let { fileItems, nvim, winid, srcId, bufnr } = this;
|
|
let info = {};
|
|
if (srcId) {
|
|
nvim.call('nvim_buf_clear_namespace', [bufnr, srcId, 0, -1], true);
|
|
for (let item of fileItems) {
|
|
for (let range of item.ranges) {
|
|
let text = `${range.start + 1}:${range.end}`;
|
|
info[range.lnum] = [range.start + 1, range.end];
|
|
nvim.call('nvim_buf_set_virtual_text', [bufnr, srcId, range.lnum - 1, [[text, 'LineNr']], {}], true);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (this.matchIds.size) {
|
|
nvim.call('coc#util#clearmatches', [Array.from(this.matchIds), this.winid], true);
|
|
this.matchIds.clear();
|
|
}
|
|
let id = 2000;
|
|
for (let item of fileItems) {
|
|
let filename = `${this.cwd ? path_1.default.relative(this.cwd, item.filepath) : item.filepath}`;
|
|
let col = string_1.byteLength(filename) + 1;
|
|
for (let range of item.ranges) {
|
|
let text = `:${range.start + 1}:${range.end}`;
|
|
for (let i = 0; i < text.length; i++) {
|
|
let ch = text[i];
|
|
this.matchIds.add(id);
|
|
info[range.lnum] = [range.start + 1, range.end];
|
|
nvim.call('matchaddpos', ['Conceal', [[range.lnum, col + i]], 99, id, { conceal: ch, window: winid }], true);
|
|
id++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.buffer.setVar('line_infos', info, true);
|
|
}
|
|
/**
|
|
* Current changed file ranges
|
|
*/
|
|
async getFileChanges() {
|
|
let changes = [];
|
|
let { document } = this;
|
|
if (!document)
|
|
return;
|
|
let lines = await document.buffer.lines;
|
|
lines.push(separator);
|
|
// current lines
|
|
let arr = [];
|
|
let fsPath;
|
|
let lnum;
|
|
for (let i = 0; i < lines.length; i++) {
|
|
let line = lines[i];
|
|
if (line.startsWith(separator)) {
|
|
if (fsPath) {
|
|
changes.push({
|
|
filepath: fsPath,
|
|
lines: arr,
|
|
lnum
|
|
});
|
|
fsPath = undefined;
|
|
arr = [];
|
|
}
|
|
if (line.length > 1) {
|
|
let ms = line.match(/^\u3000(.*)/);
|
|
if (ms) {
|
|
let filepath = ms[1].replace(/\s+$/, '');
|
|
fsPath = !path_1.default.isAbsolute(filepath) && this.cwd ? path_1.default.join(this.cwd, filepath) : filepath;
|
|
lnum = i + 1;
|
|
arr = [];
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
arr.push(line);
|
|
}
|
|
}
|
|
return changes;
|
|
}
|
|
/**
|
|
* Save changes to files, return false when no change made.
|
|
*/
|
|
async saveRefactor() {
|
|
let { nvim } = this;
|
|
let doc = this.document;
|
|
if (!doc)
|
|
return;
|
|
let { buffer } = doc;
|
|
if (workspace_1.default.isVim) {
|
|
await doc._fetchContent();
|
|
}
|
|
doc.forceSync();
|
|
let changes = await this.getFileChanges();
|
|
if (!changes)
|
|
return;
|
|
changes.sort((a, b) => a.lnum - b.lnum);
|
|
// filter changes that not change
|
|
let removeList = [];
|
|
let deltaMap = new Map();
|
|
for (let i = 0; i < changes.length; i++) {
|
|
let change = changes[i];
|
|
let { filepath, lnum } = change;
|
|
let curr = deltaMap.get(filepath) || 0;
|
|
let item = this.fileItems.find(o => o.filepath == filepath);
|
|
let range = item ? item.ranges.find(o => o.lnum == lnum) : null;
|
|
if (!range || object_1.equals(range.lines, change.lines)) {
|
|
removeList.push(i);
|
|
if (curr) {
|
|
range.start = range.start + curr;
|
|
range.end = range.end + curr;
|
|
}
|
|
continue;
|
|
}
|
|
change.start = range.start;
|
|
change.end = range.end;
|
|
if (curr != 0)
|
|
range.start = range.start + curr;
|
|
if (change.lines.length != range.lines.length) {
|
|
let delta = change.lines.length - range.lines.length;
|
|
let total = delta + curr;
|
|
deltaMap.set(filepath, total);
|
|
range.end = range.end + total;
|
|
}
|
|
else {
|
|
range.end = range.end + curr;
|
|
}
|
|
range.lines = change.lines;
|
|
}
|
|
if (removeList.length)
|
|
changes = changes.filter((_, i) => !removeList.includes(i));
|
|
if (changes.length == 0) {
|
|
workspace_1.default.showMessage('No change.', 'more');
|
|
await buffer.setOption('modified', false);
|
|
return false;
|
|
}
|
|
let changeMap = {};
|
|
for (let change of changes) {
|
|
let uri = vscode_uri_1.URI.file(change.filepath).toString();
|
|
let edits = changeMap[uri] || [];
|
|
edits.push({
|
|
range: vscode_languageserver_types_1.Range.create(change.start, 0, change.end, 0),
|
|
newText: change.lines.join('\n') + '\n'
|
|
});
|
|
changeMap[uri] = edits;
|
|
}
|
|
this.changing = true;
|
|
await workspace_1.default.applyEdit({ changes: changeMap });
|
|
this.changing = false;
|
|
nvim.pauseNotification();
|
|
buffer.setOption('modified', false, true);
|
|
nvim.command('wa', true);
|
|
this.highlightLineNr();
|
|
await nvim.resumeNotification();
|
|
return true;
|
|
}
|
|
getFileRange(lnum) {
|
|
for (let item of this.fileItems) {
|
|
for (let r of item.ranges) {
|
|
if (r.lnum == lnum) {
|
|
return r;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
async onBufferChange(e) {
|
|
if (e.bufnr == this.bufnr) {
|
|
return await this.onRefactorChange(e);
|
|
}
|
|
if (this.changing)
|
|
return;
|
|
let { uri } = e.textDocument;
|
|
let { range, text } = e.contentChanges[0];
|
|
let filepath = vscode_uri_1.URI.parse(uri).fsPath;
|
|
let fileItem = this.fileItems.find(o => o.filepath == filepath);
|
|
if (!fileItem)
|
|
return;
|
|
let lineChange = text.split('\n').length - (range.end.line - range.start.line) - 1;
|
|
let edits = [];
|
|
// 4 cases: ignore, change lineNr, reload, remove
|
|
for (let i = 0; i < fileItem.ranges.length; i++) {
|
|
let r = fileItem.ranges[i];
|
|
if (range.start.line >= r.end) {
|
|
continue;
|
|
}
|
|
if (range.end.line < r.start) {
|
|
if (lineChange == 0) {
|
|
continue;
|
|
}
|
|
else {
|
|
r.start = r.start + lineChange;
|
|
r.end = r.end + lineChange;
|
|
}
|
|
}
|
|
else {
|
|
let doc = workspace_1.default.getDocument(uri);
|
|
let newLines = doc.getLines(r.start, r.end);
|
|
if (!newLines.length) {
|
|
// remove this range
|
|
fileItem.ranges.splice(i, 1);
|
|
edits.push({
|
|
range: this.getFileRangeRange(r, false),
|
|
newText: ''
|
|
});
|
|
}
|
|
else {
|
|
r.end = r.start + newLines.length;
|
|
// reload lines, reset end
|
|
edits.push({
|
|
range: this.getFileRangeRange(r, true),
|
|
newText: newLines.join('\n') + '\n'
|
|
});
|
|
}
|
|
}
|
|
let buf = this.document.buffer;
|
|
let mod = await buf.getOption('modified');
|
|
if (edits.length) {
|
|
this.version = this.document.version;
|
|
await this.document.applyEdits(edits);
|
|
}
|
|
this.nvim.pauseNotification();
|
|
this.highlightLineNr();
|
|
if (!mod)
|
|
buf.setOption('modified', false, true);
|
|
await this.nvim.resumeNotification();
|
|
}
|
|
}
|
|
/**
|
|
* Edit range of FileRange
|
|
*/
|
|
getFileRangeRange(range, lineOnly = true) {
|
|
let { document } = this;
|
|
if (!document)
|
|
return null;
|
|
let { lnum } = range;
|
|
let first = document.getline(lnum - 1);
|
|
if (!first.startsWith('\u3000'))
|
|
return null;
|
|
let start = lineOnly ? lnum : lnum - 1;
|
|
let end = document.lineCount;
|
|
for (let i = lnum; i < document.lineCount; i++) {
|
|
let line = document.getline(i);
|
|
if (line.startsWith('\u3000')) {
|
|
end = lineOnly ? i : i + 1;
|
|
break;
|
|
}
|
|
}
|
|
return vscode_languageserver_types_1.Range.create(start, 0, end, 0);
|
|
}
|
|
/**
|
|
* Open line under cursor in split window
|
|
*/
|
|
async splitOpen() {
|
|
let { nvim } = this;
|
|
let win = nvim.createWindow(this.fromWinid);
|
|
let valid = await win.valid;
|
|
let lines = await nvim.eval('getline(1,line("."))');
|
|
let len = lines.length;
|
|
for (let i = 0; i < len; i++) {
|
|
let line = lines[len - i - 1];
|
|
let ms = line.match(/^\u3000(.+)/);
|
|
if (ms) {
|
|
let filepath = ms[1].trim();
|
|
let r = this.getLinesRange(len - i);
|
|
if (!r)
|
|
return;
|
|
let lnum = r[0] + i;
|
|
let bufname = filepath.startsWith(workspace_1.default.cwd) ? path_1.default.relative(workspace_1.default.cwd, filepath) : filepath;
|
|
nvim.pauseNotification();
|
|
if (valid) {
|
|
nvim.call('win_gotoid', [this.fromWinid], true);
|
|
this.nvim.call('coc#util#jump', ['edit', bufname, [lnum, 1]], true);
|
|
}
|
|
else {
|
|
this.nvim.call('coc#util#jump', ['belowright vs', bufname, [lnum, 1]], true);
|
|
}
|
|
nvim.command('normal! zz', true);
|
|
let [, err] = await nvim.resumeNotification();
|
|
if (err)
|
|
workspace_1.default.showMessage(`Error on open ${filepath}: ${err}`, 'error');
|
|
if (!valid) {
|
|
this.fromWinid = await nvim.call('win_getid');
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
async onRefactorChange(e) {
|
|
let { nvim } = this;
|
|
let doc = this.document;
|
|
if (doc.version - this.version == 1)
|
|
return;
|
|
let { fileItems } = this;
|
|
if (!fileItems.length)
|
|
return;
|
|
let change = e.contentChanges[0];
|
|
let { original } = e;
|
|
if (change.range.end.line < 2)
|
|
return;
|
|
doc.buffer.setOption('modified', true, true);
|
|
let { range, text } = change;
|
|
let lines = text.split('\n');
|
|
let lineChange = lines.length - (range.end.line - range.start.line) - 1;
|
|
if (lineChange == 0)
|
|
return;
|
|
let lineChanges = [];
|
|
if (text.indexOf('\u3000') !== -1) {
|
|
let startLine = range.start.line;
|
|
let diffs = fast_diff_1.default(original, text);
|
|
let offset = 0;
|
|
let orig = vscode_languageserver_types_1.TextDocument.create('file:///1', '', 0, original);
|
|
for (let i = 0; i < diffs.length; i++) {
|
|
let diff = diffs[i];
|
|
let pos = orig.positionAt(offset);
|
|
if (diff[0] == fast_diff_1.default.EQUAL) {
|
|
offset = offset + diff[1].length;
|
|
}
|
|
else if (diff[0] == fast_diff_1.default.DELETE) {
|
|
let end = orig.positionAt(offset + diff[1].length);
|
|
if (diffs[i + 1] && diffs[i + 1][0] == fast_diff_1.default.INSERT) {
|
|
let delta = diffs[i + 1][1].split('\n').length - (end.line - pos.line) - 1;
|
|
if (delta != 0)
|
|
lineChanges.push({ delta, lnum: pos.line + startLine });
|
|
i = i + 1;
|
|
}
|
|
else {
|
|
let delta = -(end.line - pos.line);
|
|
if (delta != 0)
|
|
lineChanges.push({ delta, lnum: pos.line + startLine });
|
|
}
|
|
offset = offset + diff[1].length;
|
|
}
|
|
else if (diff[0] == fast_diff_1.default.INSERT) {
|
|
let delta = diff[1].split('\n').length - 1;
|
|
if (delta != 0)
|
|
lineChanges.push({ delta, lnum: pos.line + startLine });
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
lineChanges = [{ delta: lineChange, lnum: range.start.line }];
|
|
}
|
|
let changed = false;
|
|
// adjust LineNr highlights
|
|
for (let item of fileItems) {
|
|
for (let range of item.ranges) {
|
|
let arr = lineChanges.filter(o => o.lnum < range.lnum - 1);
|
|
if (arr.length) {
|
|
let total = arr.reduce((p, c) => p + c.delta, 0);
|
|
range.lnum = range.lnum + total;
|
|
changed = true;
|
|
}
|
|
}
|
|
}
|
|
if (!changed || this.srcId)
|
|
return;
|
|
let winid = await nvim.call('win_getid');
|
|
if (winid != this.winid) {
|
|
await nvim.call('win_gotoid', [winid]);
|
|
}
|
|
nvim.pauseNotification();
|
|
this.highlightLineNr();
|
|
await nvim.resumeNotification();
|
|
}
|
|
async getItemsFromWorkspaceEdit(edit) {
|
|
let res = [];
|
|
let { beforeContext, afterContext } = this.config;
|
|
let { changes, documentChanges } = edit;
|
|
if (!changes) {
|
|
changes = {};
|
|
for (let change of documentChanges || []) {
|
|
if (vscode_languageserver_types_1.TextDocumentEdit.is(change)) {
|
|
let { textDocument, edits } = change;
|
|
changes[textDocument.uri] = edits;
|
|
}
|
|
}
|
|
}
|
|
for (let key of Object.keys(changes)) {
|
|
let max = await this.getLineCount(key);
|
|
let edits = changes[key];
|
|
let ranges = [];
|
|
// start end highlights
|
|
let start = null;
|
|
let end = null;
|
|
let highlights = [];
|
|
edits.sort((a, b) => a.range.start.line - b.range.start.line);
|
|
for (let edit of edits) {
|
|
let { line } = edit.range.start;
|
|
let s = Math.max(0, line - beforeContext);
|
|
if (start != null && s < end) {
|
|
end = Math.min(max, line + afterContext + 1);
|
|
highlights.push(adjustRange(edit.range, start));
|
|
}
|
|
else {
|
|
if (start != null)
|
|
ranges.push({ start, end, highlights });
|
|
start = s;
|
|
end = Math.min(max, line + afterContext + 1);
|
|
highlights = [adjustRange(edit.range, start)];
|
|
}
|
|
}
|
|
if (start != null)
|
|
ranges.push({ start, end, highlights });
|
|
res.push({
|
|
ranges,
|
|
filepath: vscode_uri_1.URI.parse(key).fsPath
|
|
});
|
|
}
|
|
return res;
|
|
}
|
|
async getLineCount(uri) {
|
|
let doc = workspace_1.default.getDocument(uri);
|
|
if (doc)
|
|
return doc.lineCount;
|
|
return await fs_1.getFileLineCount(vscode_uri_1.URI.parse(uri).fsPath);
|
|
}
|
|
async getLines(fsPath, start, end) {
|
|
let uri = vscode_uri_1.URI.file(fsPath).toString();
|
|
let doc = workspace_1.default.getDocument(uri);
|
|
if (doc)
|
|
return doc.getLines(start, end);
|
|
return await fs_1.readFileLines(fsPath, start, end - 1);
|
|
}
|
|
getLinesRange(lnum) {
|
|
for (let item of this.fileItems) {
|
|
for (let range of item.ranges) {
|
|
if (range.lnum == lnum) {
|
|
return [range.start, range.end];
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
dispose() {
|
|
this.fileItems = [];
|
|
util_1.disposeAll(this.disposables);
|
|
}
|
|
/**
|
|
* Refactor from workspaceEdit.
|
|
*/
|
|
static async createFromWorkspaceEdit(edit, filetype) {
|
|
if (!edit || emptyWorkspaceEdit(edit))
|
|
return null;
|
|
let refactor = new Refactor();
|
|
await refactor.fromWorkspaceEdit(edit, filetype);
|
|
return refactor;
|
|
}
|
|
/**
|
|
* Refactor from locations.
|
|
*/
|
|
static async createFromLocations(locations, filetype) {
|
|
if (!locations || locations.length == 0)
|
|
return null;
|
|
let changes = {};
|
|
let edit = { changes };
|
|
for (let location of locations) {
|
|
let edits = changes[location.uri] || [];
|
|
edits.push({ range: location.range, newText: '' });
|
|
changes[location.uri] = edits;
|
|
}
|
|
let refactor = new Refactor();
|
|
await refactor.fromWorkspaceEdit(edit, filetype);
|
|
return refactor;
|
|
}
|
|
static async createFromLines(lines) {
|
|
let refactor = new Refactor();
|
|
await refactor.fromLines(lines);
|
|
return refactor;
|
|
}
|
|
}
|
|
exports.default = Refactor;
|
|
function adjustRange(range, offset) {
|
|
let { start, end } = range;
|
|
return vscode_languageserver_types_1.Range.create(start.line - offset, start.character, end.line - offset, end.character);
|
|
}
|
|
function emptyWorkspaceEdit(edit) {
|
|
let { changes, documentChanges } = edit;
|
|
if (documentChanges && documentChanges.length)
|
|
return false;
|
|
if (changes && Object.keys(changes).length)
|
|
return false;
|
|
return true;
|
|
}
|
|
//# sourceMappingURL=refactor.js.map
|
|
|
|
/***/ }),
|
|
/* 405 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const await_semaphore_1 = __webpack_require__(406);
|
|
const child_process_1 = __webpack_require__(175);
|
|
const events_1 = __webpack_require__(49);
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const readline_1 = tslib_1.__importDefault(__webpack_require__(60));
|
|
const vscode_languageserver_types_1 = __webpack_require__(161);
|
|
const which_1 = tslib_1.__importDefault(__webpack_require__(181));
|
|
const highligher_1 = tslib_1.__importDefault(__webpack_require__(349));
|
|
const ansiparse_1 = __webpack_require__(350);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const logger = __webpack_require__(186)('handler-search');
|
|
const defaultArgs = ['--color', 'ansi', '--colors', 'path:fg:black', '--colors', 'line:fg:green', '--colors', 'match:fg:red', '--no-messages', '--heading', '-n'];
|
|
const controlCode = '\x1b';
|
|
// emit FileItem
|
|
class Task extends events_1.EventEmitter {
|
|
start(cmd, args, cwd) {
|
|
this.process = child_process_1.spawn(cmd, args, { cwd });
|
|
this.process.on('error', e => {
|
|
this.emit('error', e.message);
|
|
});
|
|
const rl = readline_1.default.createInterface(this.process.stdout);
|
|
let start;
|
|
let fileItem;
|
|
let lines = [];
|
|
let highlights = [];
|
|
let create = true;
|
|
rl.on('line', content => {
|
|
if (content.indexOf(controlCode) !== -1) {
|
|
let items = ansiparse_1.ansiparse(content);
|
|
if (items[0].foreground == 'black') {
|
|
fileItem = { filepath: path_1.default.join(cwd, items[0].text), ranges: [] };
|
|
return;
|
|
}
|
|
let normalLine = items[0].foreground == 'green';
|
|
if (normalLine) {
|
|
let lnum = parseInt(items[0].text, 10) - 1;
|
|
let padlen = items[0].text.length + 1;
|
|
if (create) {
|
|
start = lnum;
|
|
create = false;
|
|
}
|
|
let line = '';
|
|
for (let item of items) {
|
|
if (item.foreground == 'red') {
|
|
let l = lnum - start;
|
|
let c = line.length - padlen;
|
|
highlights.push(vscode_languageserver_types_1.Range.create(l, c, l, c + item.text.length));
|
|
}
|
|
line += item.text;
|
|
}
|
|
let currline = line.slice(padlen);
|
|
lines.push(currline);
|
|
}
|
|
}
|
|
else {
|
|
let fileEnd = content.trim().length == 0;
|
|
if (fileItem && (fileEnd || content.trim() == '--')) {
|
|
let fileRange = {
|
|
lines,
|
|
highlights,
|
|
start,
|
|
end: start + lines.length
|
|
};
|
|
fileItem.ranges.push(fileRange);
|
|
}
|
|
if (fileEnd) {
|
|
this.emit('item', fileItem);
|
|
fileItem = null;
|
|
}
|
|
lines = [];
|
|
highlights = [];
|
|
create = true;
|
|
}
|
|
});
|
|
rl.on('close', () => {
|
|
if (fileItem) {
|
|
if (lines.length) {
|
|
let fileRange = {
|
|
lines,
|
|
highlights,
|
|
start,
|
|
end: start + lines.length
|
|
};
|
|
fileItem.ranges.push(fileRange);
|
|
}
|
|
this.emit('item', fileItem);
|
|
}
|
|
lines = highlights = fileItem = null;
|
|
this.emit('end');
|
|
});
|
|
}
|
|
dispose() {
|
|
if (this.process) {
|
|
this.process.kill();
|
|
}
|
|
}
|
|
}
|
|
class Search {
|
|
constructor(nvim, cmd = 'rg') {
|
|
this.nvim = nvim;
|
|
this.cmd = cmd;
|
|
}
|
|
run(args, cwd, refactor) {
|
|
let { nvim, cmd } = this;
|
|
let { afterContext, beforeContext } = refactor.config;
|
|
let argList = ['-A', afterContext.toString(), '-B', beforeContext.toString()].concat(defaultArgs, args);
|
|
argList.push('--', './');
|
|
try {
|
|
cmd = which_1.default.sync(cmd);
|
|
}
|
|
catch (e) {
|
|
workspace_1.default.showMessage('Please install ripgrep and make sure rg is in your $PATH', 'error');
|
|
return Promise.reject(e);
|
|
}
|
|
this.task = new Task();
|
|
this.task.start(cmd, argList, cwd);
|
|
let mutex = new await_semaphore_1.Mutex();
|
|
let files = 0;
|
|
let matches = 0;
|
|
let start = Date.now();
|
|
// remaining items
|
|
let fileItems = [];
|
|
const addFileItems = async () => {
|
|
if (fileItems.length == 0)
|
|
return;
|
|
let items = fileItems.slice();
|
|
fileItems = [];
|
|
const release = await mutex.acquire();
|
|
try {
|
|
await refactor.addFileItems(items);
|
|
}
|
|
catch (e) {
|
|
logger.error(e);
|
|
}
|
|
release();
|
|
};
|
|
return new Promise((resolve, reject) => {
|
|
let interval = setInterval(addFileItems, 100);
|
|
this.task.on('item', async (fileItem) => {
|
|
files++;
|
|
matches = matches + fileItem.ranges.reduce((p, r) => p + r.highlights.length, 0);
|
|
fileItems.push(fileItem);
|
|
});
|
|
this.task.on('error', message => {
|
|
clearInterval(interval);
|
|
workspace_1.default.showMessage(`Error on command "${cmd}": ${message}`, 'error');
|
|
this.task = null;
|
|
reject(new Error(message));
|
|
});
|
|
this.task.on('end', async () => {
|
|
clearInterval(interval);
|
|
try {
|
|
await addFileItems();
|
|
const release = await mutex.acquire();
|
|
release();
|
|
this.task.removeAllListeners();
|
|
this.task = null;
|
|
let { document } = refactor;
|
|
if (document) {
|
|
let buf = document.buffer;
|
|
nvim.pauseNotification();
|
|
if (files == 0) {
|
|
buf.setLines(['No match found'], { start: 1, end: 2, strictIndexing: false });
|
|
buf.addHighlight({ line: 1, srcId: -1, colEnd: -1, colStart: 0, hlGroup: 'Error' }).logError();
|
|
buf.setOption('modified', false, true);
|
|
}
|
|
else {
|
|
let highligher = new highligher_1.default();
|
|
highligher.addText('Files', 'MoreMsg');
|
|
highligher.addText(': ');
|
|
highligher.addText(`${files} `, 'Number');
|
|
highligher.addText('Matches', 'MoreMsg');
|
|
highligher.addText(': ');
|
|
highligher.addText(`${matches} `, 'Number');
|
|
highligher.addText('Duration', 'MoreMsg');
|
|
highligher.addText(': ');
|
|
highligher.addText(`${Date.now() - start}ms`, 'Number');
|
|
highligher.render(buf, 1, 2);
|
|
}
|
|
buf.setOption('modified', false, true);
|
|
await nvim.resumeNotification(false, true);
|
|
}
|
|
}
|
|
catch (e) {
|
|
reject(e);
|
|
return;
|
|
}
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
exports.default = Search;
|
|
//# sourceMappingURL=search.js.map
|
|
|
|
/***/ }),
|
|
/* 406 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
class Semaphore {
|
|
constructor(count) {
|
|
this.tasks = [];
|
|
this.count = count;
|
|
}
|
|
sched() {
|
|
if (this.count > 0 && this.tasks.length > 0) {
|
|
this.count--;
|
|
let next = this.tasks.shift();
|
|
if (next === undefined) {
|
|
throw "Unexpected undefined value in tasks list";
|
|
}
|
|
next();
|
|
}
|
|
}
|
|
acquire() {
|
|
return new Promise((res, rej) => {
|
|
var task = () => {
|
|
var released = false;
|
|
res(() => {
|
|
if (!released) {
|
|
released = true;
|
|
this.count++;
|
|
this.sched();
|
|
}
|
|
});
|
|
};
|
|
this.tasks.push(task);
|
|
if (process && process.nextTick) {
|
|
process.nextTick(this.sched.bind(this));
|
|
}
|
|
else {
|
|
setImmediate(this.sched.bind(this));
|
|
}
|
|
});
|
|
}
|
|
use(f) {
|
|
return this.acquire()
|
|
.then(release => {
|
|
return f()
|
|
.then((res) => {
|
|
release();
|
|
return res;
|
|
})
|
|
.catch((err) => {
|
|
release();
|
|
throw err;
|
|
});
|
|
});
|
|
}
|
|
}
|
|
exports.Semaphore = Semaphore;
|
|
class Mutex extends Semaphore {
|
|
constructor() {
|
|
super(1);
|
|
}
|
|
}
|
|
exports.Mutex = Mutex;
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
/* 407 */
|
|
/***/ (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__(209));
|
|
const debounce_1 = tslib_1.__importDefault(__webpack_require__(176));
|
|
const vscode_languageserver_types_1 = __webpack_require__(161);
|
|
const events_1 = tslib_1.__importDefault(__webpack_require__(148));
|
|
const util_1 = __webpack_require__(174);
|
|
const array_1 = __webpack_require__(212);
|
|
const position_1 = __webpack_require__(213);
|
|
const workspace_1 = tslib_1.__importDefault(__webpack_require__(187));
|
|
const range_1 = tslib_1.__importDefault(__webpack_require__(408));
|
|
const logger = __webpack_require__(186)('cursors');
|
|
class Cursors {
|
|
constructor(nvim) {
|
|
this.nvim = nvim;
|
|
this._activated = false;
|
|
this._changed = false;
|
|
this.ranges = [];
|
|
this.disposables = [];
|
|
this.matchIds = [];
|
|
this.version = -1;
|
|
this.loadConfig();
|
|
workspace_1.default.onDidChangeConfiguration(e => {
|
|
if (e.affectsConfiguration('cursors')) {
|
|
this.loadConfig();
|
|
}
|
|
});
|
|
}
|
|
loadConfig() {
|
|
let config = workspace_1.default.getConfiguration('cursors');
|
|
this.config = {
|
|
nextKey: config.get('nextKey', '<C-n>'),
|
|
previousKey: config.get('previousKey', '<C-p>'),
|
|
cancelKey: config.get('cancelKey', '<esc>')
|
|
};
|
|
}
|
|
async select(bufnr, kind, mode) {
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return;
|
|
doc.forceSync();
|
|
let { nvim } = this;
|
|
if (this._changed || bufnr != this.bufnr) {
|
|
this.cancel();
|
|
}
|
|
let pos = await workspace_1.default.getCursorPosition();
|
|
let range;
|
|
if (kind == 'operator') {
|
|
await nvim.command(`normal! ${mode == 'line' ? `'[` : '`['}`);
|
|
let start = await workspace_1.default.getCursorPosition();
|
|
await nvim.command(`normal! ${mode == 'line' ? `']` : '`]'}`);
|
|
let end = await workspace_1.default.getCursorPosition();
|
|
await workspace_1.default.moveTo(pos);
|
|
let relative = position_1.comparePosition(start, end);
|
|
// do nothing for empty range
|
|
if (relative == 0)
|
|
return;
|
|
if (relative >= 0)
|
|
[start, end] = [end, start];
|
|
// include end character
|
|
let line = doc.getline(end.line);
|
|
if (end.character < line.length) {
|
|
end.character = end.character + 1;
|
|
}
|
|
let ranges = splitRange(doc, vscode_languageserver_types_1.Range.create(start, end));
|
|
for (let r of ranges) {
|
|
let text = doc.textDocument.getText(r);
|
|
this.addRange(r, text);
|
|
}
|
|
}
|
|
else if (kind == 'word') {
|
|
range = doc.getWordRangeAtPosition(pos);
|
|
if (!range) {
|
|
let line = doc.getline(pos.line);
|
|
if (pos.character == line.length) {
|
|
range = vscode_languageserver_types_1.Range.create(pos.line, Math.max(0, line.length - 1), pos.line, line.length);
|
|
}
|
|
else {
|
|
range = vscode_languageserver_types_1.Range.create(pos.line, pos.character, pos.line, pos.character + 1);
|
|
}
|
|
}
|
|
let line = doc.getline(pos.line);
|
|
let text = line.slice(range.start.character, range.end.character);
|
|
this.addRange(range, text);
|
|
}
|
|
else if (kind == 'position') {
|
|
// make sure range contains character for highlight
|
|
let line = doc.getline(pos.line);
|
|
if (pos.character >= line.length) {
|
|
range = vscode_languageserver_types_1.Range.create(pos.line, line.length - 1, pos.line, line.length);
|
|
}
|
|
else {
|
|
range = vscode_languageserver_types_1.Range.create(pos.line, pos.character, pos.line, pos.character + 1);
|
|
}
|
|
this.addRange(range, line.slice(range.start.character, range.end.character));
|
|
}
|
|
else if (kind == 'range') {
|
|
await nvim.call('eval', 'feedkeys("\\<esc>", "in")');
|
|
let range = await workspace_1.default.getSelectedRange(mode, doc);
|
|
if (!range || position_1.comparePosition(range.start, range.end) == 0)
|
|
return;
|
|
let ranges = mode == '\x16' ? getVisualRanges(doc, range) : splitRange(doc, range);
|
|
for (let r of ranges) {
|
|
let text = doc.textDocument.getText(r);
|
|
this.addRange(r, text);
|
|
}
|
|
}
|
|
else {
|
|
workspace_1.default.showMessage(`${kind} not supported`, 'error');
|
|
return;
|
|
}
|
|
if (this._activated && !this.ranges.length) {
|
|
this.cancel();
|
|
}
|
|
else if (this.ranges.length && !this._activated) {
|
|
let winid = await nvim.call('win_getid');
|
|
this.activate(doc, winid);
|
|
}
|
|
if (this._activated) {
|
|
nvim.pauseNotification();
|
|
this.doHighlights();
|
|
let [, err] = await nvim.resumeNotification();
|
|
if (err)
|
|
logger.error(err);
|
|
}
|
|
if (kind == 'word' || kind == 'position') {
|
|
await nvim.command(`silent! call repeat#set("\\<Plug>(coc-cursors-${kind})", -1)`);
|
|
}
|
|
}
|
|
activate(doc, winid) {
|
|
if (this._activated)
|
|
return;
|
|
this._activated = true;
|
|
this.bufnr = doc.bufnr;
|
|
this.winid = winid;
|
|
this.nvim.setVar('coc_cursors_activated', 1, true);
|
|
doc.forceSync();
|
|
this.textDocument = doc.textDocument;
|
|
workspace_1.default.onDidChangeTextDocument(async (e) => {
|
|
if (e.textDocument.uri != doc.uri)
|
|
return;
|
|
if (doc.version - this.version == 1 || !this.ranges.length)
|
|
return;
|
|
let change = e.contentChanges[0];
|
|
let { original } = e;
|
|
let { text, range } = change;
|
|
// ignore change after last range
|
|
if (position_1.comparePosition(range.start, this.lastPosition) > 0) {
|
|
if (this._changed) {
|
|
this.cancel();
|
|
}
|
|
else {
|
|
this.textDocument = doc.textDocument;
|
|
}
|
|
return;
|
|
}
|
|
let changeCount = text.split('\n').length - (range.end.line - range.start.line + 1);
|
|
// adjust line when change before first position
|
|
let d = position_1.comparePosition(range.end, this.firstPosition);
|
|
if (d < 0 || d == 0 && (position_1.comparePosition(range.start, range.end) != 0 || text.endsWith('\n'))) {
|
|
if (this._changed) {
|
|
this.cancel();
|
|
}
|
|
else {
|
|
if (changeCount != 0)
|
|
this.ranges.forEach(r => r.line = r.line + changeCount);
|
|
this.textDocument = doc.textDocument;
|
|
}
|
|
return;
|
|
}
|
|
// ignore changes when not overlap
|
|
if (changeCount == 0) {
|
|
let lnums = array_1.distinct(this.ranges.map(r => r.line));
|
|
let startLine = range.start.line;
|
|
let endLine = range.end.line;
|
|
let overlap = lnums.some(line => line >= startLine && line <= endLine);
|
|
if (!overlap)
|
|
return;
|
|
}
|
|
this._changed = true;
|
|
// get range from edit
|
|
let textRange = this.getTextRange(range, text);
|
|
if (textRange) {
|
|
await this.applySingleEdit(textRange, { range, newText: text });
|
|
}
|
|
else {
|
|
await this.applyComposedEdit(original, { range, newText: text });
|
|
}
|
|
}, null, this.disposables);
|
|
let { cancelKey, nextKey, previousKey } = this.config;
|
|
workspace_1.default.registerLocalKeymap('n', cancelKey, () => {
|
|
if (!this._activated)
|
|
return this.unmap(cancelKey);
|
|
this.cancel();
|
|
}, true);
|
|
workspace_1.default.registerLocalKeymap('n', nextKey, async () => {
|
|
if (!this._activated)
|
|
return this.unmap(nextKey);
|
|
let ranges = this.ranges.map(o => o.currRange);
|
|
let curr = await workspace_1.default.getCursorPosition();
|
|
for (let r of ranges) {
|
|
if (position_1.comparePosition(r.start, curr) > 0) {
|
|
await workspace_1.default.moveTo(r.start);
|
|
return;
|
|
}
|
|
}
|
|
if (ranges.length)
|
|
await workspace_1.default.moveTo(ranges[0].start);
|
|
}, true);
|
|
workspace_1.default.registerLocalKeymap('n', previousKey, async () => {
|
|
if (!this._activated)
|
|
return this.unmap(previousKey);
|
|
let ranges = this.ranges.map(o => o.currRange);
|
|
ranges.reverse();
|
|
let curr = await workspace_1.default.getCursorPosition();
|
|
for (let r of ranges) {
|
|
if (position_1.comparePosition(r.end, curr) < 0) {
|
|
await workspace_1.default.moveTo(r.start);
|
|
return;
|
|
}
|
|
}
|
|
if (ranges.length)
|
|
await workspace_1.default.moveTo(ranges[0].start);
|
|
}, true);
|
|
events_1.default.on('CursorMoved', debounce_1.default(async (bufnr) => {
|
|
if (bufnr != this.bufnr)
|
|
return this.cancel();
|
|
let winid = await this.nvim.call('win_getid');
|
|
if (winid != this.winid) {
|
|
this.cancel();
|
|
}
|
|
}, 100), null, this.disposables);
|
|
}
|
|
doHighlights() {
|
|
let { matchIds } = this;
|
|
let doc = workspace_1.default.getDocument(this.bufnr);
|
|
if (!doc || !this.ranges.length)
|
|
return;
|
|
if (matchIds.length)
|
|
this.nvim.call('coc#util#clearmatches', [matchIds, this.winid], true);
|
|
let searchRanges = this.ranges.map(o => o.currRange);
|
|
this.matchIds = doc.matchAddRanges(searchRanges, 'CocCursorRange', 99);
|
|
if (workspace_1.default.isVim)
|
|
this.nvim.command('redraw', true);
|
|
}
|
|
cancel() {
|
|
if (!this._activated)
|
|
return;
|
|
let { matchIds } = this;
|
|
this.nvim.setVar('coc_cursors_activated', 0, true);
|
|
this.nvim.call('coc#util#clearmatches', [Array.from(matchIds), this.winid], true);
|
|
this.matchIds = [];
|
|
util_1.disposeAll(this.disposables);
|
|
this._changed = false;
|
|
this.ranges = [];
|
|
this.version = -1;
|
|
this._activated = false;
|
|
}
|
|
unmap(key) {
|
|
let { nvim, bufnr } = this;
|
|
let { cancelKey, nextKey, previousKey } = this.config;
|
|
let escaped = key.startsWith('<') && key.endsWith('>') ? `\\${key}` : key;
|
|
nvim.pauseNotification();
|
|
nvim.call('coc#util#unmap', [bufnr, [cancelKey, nextKey, previousKey]], true);
|
|
nvim.call('eval', `feedkeys("${escaped}", 't')`, true);
|
|
nvim.resumeNotification(false, true).logError();
|
|
}
|
|
// Add ranges to current document
|
|
async addRanges(ranges) {
|
|
let { nvim } = this;
|
|
let [bufnr, winid] = await nvim.eval('[bufnr("%"),win_getid()]');
|
|
if (this._activated && (this.bufnr != bufnr || this.winid != winid)) {
|
|
this.cancel();
|
|
}
|
|
let doc = workspace_1.default.getDocument(bufnr);
|
|
if (!doc)
|
|
return;
|
|
doc.forceSync();
|
|
// filter overlap ranges
|
|
if (!this._changed) {
|
|
this.ranges = this.ranges.filter(r => {
|
|
let { currRange } = r;
|
|
return !ranges.some(range => position_1.rangeOverlap(range, currRange));
|
|
});
|
|
}
|
|
else {
|
|
// use new ranges
|
|
this.ranges = [];
|
|
}
|
|
let { textDocument } = doc;
|
|
for (let range of ranges) {
|
|
let { line } = range.start;
|
|
let textRange = new range_1.default(line, range.start.character, range.end.character, textDocument.getText(range), 0);
|
|
this.ranges.push(textRange);
|
|
}
|
|
this.ranges.sort((a, b) => position_1.comparePosition(a.range.start, b.range.start));
|
|
// fix preCount
|
|
let preCount = 0;
|
|
let currline = -1;
|
|
for (let range of this.ranges) {
|
|
let { line } = range;
|
|
if (line != currline) {
|
|
preCount = 0;
|
|
}
|
|
range.preCount = preCount;
|
|
preCount = preCount + 1;
|
|
currline = line;
|
|
}
|
|
if (!this.ranges.length)
|
|
return;
|
|
this.activate(doc, winid);
|
|
nvim.pauseNotification();
|
|
this.doHighlights();
|
|
let [, err] = await nvim.resumeNotification();
|
|
if (err)
|
|
logger.error(err);
|
|
}
|
|
get activated() {
|
|
return this._activated;
|
|
}
|
|
/**
|
|
* Find single range from edit
|
|
*/
|
|
getTextRange(range, text) {
|
|
let { ranges } = this;
|
|
// can't support line count change
|
|
if (text.indexOf('\n') !== -1 || range.start.line != range.end.line)
|
|
return null;
|
|
ranges.sort((a, b) => {
|
|
if (a.line != b.line)
|
|
return a.line - b.line;
|
|
return a.currRange.start.character - b.currRange.start.character;
|
|
});
|
|
for (let i = 0; i < ranges.length; i++) {
|
|
let r = ranges[i];
|
|
if (position_1.rangeInRange(range, r.currRange)) {
|
|
return r;
|
|
}
|
|
if (r.line != range.start.line) {
|
|
continue;
|
|
}
|
|
if (text.length && range.start.character == r.currRange.end.character) {
|
|
// end add
|
|
let next = ranges[i + 1];
|
|
if (!next)
|
|
return r;
|
|
return position_1.positionInRange(next.currRange.start, range) ? null : r;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
async applySingleEdit(textRange, edit) {
|
|
// single range change, calculate & apply changes for all ranges
|
|
let { range, newText } = edit;
|
|
let doc = workspace_1.default.getDocument(this.bufnr);
|
|
this.adjustChange(textRange, range, newText);
|
|
if (this.ranges.length == 1) {
|
|
this.doHighlights();
|
|
return;
|
|
}
|
|
let edits = this.ranges.map(o => o.textEdit);
|
|
let content = vscode_languageserver_types_1.TextDocument.applyEdits(this.textDocument, edits);
|
|
let newLines = content.split('\n');
|
|
let changedLnum = new Set();
|
|
let arr = [];
|
|
for (let r of this.ranges) {
|
|
if (!changedLnum.has(r.line)) {
|
|
changedLnum.add(r.line);
|
|
arr.push([r.line, newLines[r.line]]);
|
|
}
|
|
}
|
|
let { nvim } = this;
|
|
this.version = doc.version;
|
|
// apply changes
|
|
nvim.pauseNotification();
|
|
nvim.command('undojoin', true);
|
|
doc.changeLines(arr);
|
|
let { cursor } = events_1.default;
|
|
if (textRange.preCount > 0 && cursor.bufnr == this.bufnr && textRange.line + 1 == cursor.lnum) {
|
|
let changed = textRange.preCount * (newText.length - (range.end.character - range.start.character));
|
|
nvim.call('cursor', [cursor.lnum, cursor.col + changed], true);
|
|
}
|
|
this.doHighlights();
|
|
let [, err] = await nvim.resumeNotification();
|
|
if (err)
|
|
logger.error(err);
|
|
}
|
|
async applyComposedEdit(original, edit) {
|
|
// check complex edit
|
|
let { range, newText } = edit;
|
|
let { nvim, ranges } = this;
|
|
let doc = vscode_languageserver_types_1.TextDocument.create('file:///1', '', 0, original);
|
|
let edits = [];
|
|
let diffs = fast_diff_1.default(original, newText);
|
|
let offset = 0;
|
|
for (let i = 0; i < diffs.length; i++) {
|
|
let diff = diffs[i];
|
|
let pos = adjustPosition(range.start, doc.positionAt(offset));
|
|
if (diff[0] == fast_diff_1.default.EQUAL) {
|
|
offset = offset + diff[1].length;
|
|
}
|
|
else if (diff[0] == fast_diff_1.default.DELETE) {
|
|
let end = adjustPosition(range.start, doc.positionAt(offset + diff[1].length));
|
|
if (diffs[i + 1] && diffs[i + 1][0] == fast_diff_1.default.INSERT) {
|
|
// change
|
|
edits.push({ range: vscode_languageserver_types_1.Range.create(pos, end), newText: diffs[i + 1][1] });
|
|
i = i + 1;
|
|
}
|
|
else {
|
|
// delete
|
|
edits.push({ range: vscode_languageserver_types_1.Range.create(pos, end), newText: '' });
|
|
}
|
|
offset = offset + diff[1].length;
|
|
}
|
|
else if (diff[0] == fast_diff_1.default.INSERT) {
|
|
edits.push({ range: vscode_languageserver_types_1.Range.create(pos, pos), newText: diff[1] });
|
|
}
|
|
}
|
|
if (edits.some(edit => edit.newText.indexOf('\n') != -1 || edit.range.start.line != edit.range.end.line)) {
|
|
this.cancel();
|
|
return;
|
|
}
|
|
if (edits.length == ranges.length) {
|
|
let last;
|
|
for (let i = 0; i < edits.length; i++) {
|
|
let edit = edits[i];
|
|
let textRange = this.ranges[i];
|
|
if (!position_1.rangeIntersect(textRange.currRange, edit.range)) {
|
|
this.cancel();
|
|
return;
|
|
}
|
|
if (last && !equalEdit(edit, last)) {
|
|
this.cancel();
|
|
return;
|
|
}
|
|
textRange.applyEdit(edit);
|
|
last = edit;
|
|
}
|
|
}
|
|
else if (edits.length == ranges.length * 2) {
|
|
for (let i = 0; i < edits.length - 1; i = i + 2) {
|
|
let edit = edits[i];
|
|
let next = edits[i + 1];
|
|
if (edit.newText.length == 0 && next.newText.length == 0) {
|
|
// remove begin & end
|
|
let textRange = this.ranges[i / 2];
|
|
if (position_1.comparePosition(textRange.currRange.end, next.range.end) != 0) {
|
|
this.cancel();
|
|
return;
|
|
}
|
|
let start = edit.range.start.character - textRange.currRange.start.character;
|
|
textRange.replace(start, edit.range.end.character - edit.range.start.character, '');
|
|
let offset = next.range.end.character - next.range.start.character;
|
|
let len = textRange.text.length;
|
|
textRange.replace(len - offset, len);
|
|
}
|
|
else if (position_1.emptyRange(edit.range) && position_1.emptyRange(next.range)) {
|
|
// add begin & end
|
|
let textRange = this.ranges[i / 2];
|
|
if (position_1.comparePosition(textRange.currRange.end, next.range.start) != 0) {
|
|
this.cancel();
|
|
return;
|
|
}
|
|
let start = edit.range.start.character - textRange.currRange.start.character;
|
|
textRange.add(start, edit.newText);
|
|
let len = textRange.text.length;
|
|
textRange.add(len, next.newText);
|
|
}
|
|
else {
|
|
this.cancel();
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
this.cancel();
|
|
}
|
|
nvim.pauseNotification();
|
|
this.doHighlights();
|
|
await nvim.resumeNotification(false, true);
|
|
}
|
|
adjustChange(textRange, range, text) {
|
|
let { ranges } = this;
|
|
if (range.start.character == range.end.character) {
|
|
// add
|
|
let isEnd = textRange.currRange.end.character == range.start.character;
|
|
if (isEnd) {
|
|
ranges.forEach(r => {
|
|
r.add(r.text.length, text);
|
|
});
|
|
}
|
|
else {
|
|
let d = range.start.character - textRange.currRange.start.character;
|
|
ranges.forEach(r => {
|
|
r.add(Math.min(r.text.length, d), text);
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
// replace
|
|
let d = range.end.character - range.start.character;
|
|
let isEnd = textRange.currRange.end.character == range.end.character;
|
|
if (isEnd) {
|
|
if (textRange.currRange.start.character == range.start.character) {
|
|
// changed both start and end
|
|
if (text.indexOf(textRange.text) !== -1) {
|
|
let idx = text.indexOf(textRange.text);
|
|
let pre = idx == 0 ? '' : text.slice(0, idx);
|
|
let post = text.slice(idx + textRange.text.length);
|
|
if (pre)
|
|
ranges.forEach(r => r.add(0, pre));
|
|
if (post)
|
|
ranges.forEach(r => r.add(r.text.length, post));
|
|
}
|
|
else if (textRange.text.indexOf(text) !== -1) {
|
|
// delete
|
|
let idx = textRange.text.indexOf(text);
|
|
let offset = textRange.text.length - (idx + text.length);
|
|
if (idx != 0)
|
|
ranges.forEach(r => r.replace(0, idx));
|
|
if (offset > 0)
|
|
ranges.forEach(r => r.replace(r.text.length - offset, r.text.length));
|
|
}
|
|
else {
|
|
this.cancel();
|
|
}
|
|
}
|
|
else {
|
|
ranges.forEach(r => {
|
|
let l = r.text.length;
|
|
r.replace(Math.max(0, l - d), l, text);
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
let start = range.start.character - textRange.currRange.start.character;
|
|
ranges.forEach(r => {
|
|
let l = r.text.length;
|
|
r.replace(start, Math.min(start + d, l), text);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
addRange(range, text) {
|
|
let { ranges } = this;
|
|
let idx = ranges.findIndex(o => position_1.rangeIntersect(o.range, range));
|
|
// remove range when intersect
|
|
if (idx !== -1) {
|
|
ranges.splice(idx, 1);
|
|
// adjust preCount after
|
|
for (let r of ranges) {
|
|
if (r.line == range.start.line && r.start > range.start.character) {
|
|
r.preCount = r.preCount - 1;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
let preCount = 0;
|
|
let idx = 0;
|
|
let { line } = range.start;
|
|
// idx & preCount
|
|
for (let r of ranges) {
|
|
if (r.line > line || (r.line == line && r.start > range.end.character)) {
|
|
break;
|
|
}
|
|
if (r.line == line)
|
|
preCount++;
|
|
idx++;
|
|
}
|
|
let created = new range_1.default(line, range.start.character, range.end.character, text, preCount);
|
|
ranges.splice(idx, 0, created);
|
|
// adjust preCount after
|
|
for (let r of ranges) {
|
|
if (r.line == range.start.line && r.start > range.start.character) {
|
|
r.preCount = r.preCount + 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
get lastPosition() {
|
|
let { ranges } = this;
|
|
let r = ranges[ranges.length - 1];
|
|
return r.currRange.end;
|
|
}
|
|
get firstPosition() {
|
|
let { ranges } = this;
|
|
return ranges[0].currRange.start;
|
|
}
|
|
}
|
|
exports.default = Cursors;
|
|
function splitRange(doc, range) {
|
|
let splited = [];
|
|
for (let i = range.start.line; i <= range.end.line; i++) {
|
|
let curr = doc.getline(i) || '';
|
|
let sc = i == range.start.line ? range.start.character : 0;
|
|
let ec = i == range.end.line ? range.end.character : curr.length;
|
|
if (sc == ec)
|
|
continue;
|
|
splited.push(vscode_languageserver_types_1.Range.create(i, sc, i, ec));
|
|
}
|
|
return splited;
|
|
}
|
|
/**
|
|
* Get ranges of visual block
|
|
*/
|
|
function getVisualRanges(doc, range) {
|
|
let { start, end } = range;
|
|
if (start.line > end.line) {
|
|
[start, end] = [end, start];
|
|
}
|
|
let sc = start.character < end.character ? start.character : end.character;
|
|
let ec = start.character < end.character ? end.character : start.character;
|
|
let ranges = [];
|
|
for (let i = start.line; i <= end.line; i++) {
|
|
let line = doc.getline(i);
|
|
ranges.push(vscode_languageserver_types_1.Range.create(i, sc, i, Math.min(line.length, ec)));
|
|
}
|
|
return ranges;
|
|
}
|
|
function adjustPosition(position, delta) {
|
|
let { line, character } = delta;
|
|
return vscode_languageserver_types_1.Position.create(position.line + line, line == 0 ? position.character + character : character);
|
|
}
|
|
function equalEdit(one, two) {
|
|
if (one.newText.length != two.newText.length)
|
|
return false;
|
|
let { range } = one;
|
|
if (range.end.character - range.start.character != two.range.end.character - two.range.start.character) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
/* 408 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const vscode_languageserver_types_1 = __webpack_require__(161);
|
|
const logger = __webpack_require__(186)('cursors-range');
|
|
// edit range
|
|
class TextRange {
|
|
constructor(line, start, end, text,
|
|
// range count at this line before, shuld be updated on range add
|
|
preCount) {
|
|
this.line = line;
|
|
this.start = start;
|
|
this.end = end;
|
|
this.text = text;
|
|
this.preCount = preCount;
|
|
this.currStart = start;
|
|
this.currEnd = end;
|
|
}
|
|
add(offset, add) {
|
|
let { text, preCount } = this;
|
|
let pre = offset == 0 ? '' : text.slice(0, offset);
|
|
let post = text.slice(offset);
|
|
this.text = `${pre}${add}${post}`;
|
|
this.currStart = this.currStart + preCount * add.length;
|
|
this.currEnd = this.currEnd + (preCount + 1) * add.length;
|
|
}
|
|
replace(begin, end, add = '') {
|
|
let { text, preCount } = this;
|
|
let pre = begin == 0 ? '' : text.slice(0, begin);
|
|
let post = text.slice(end);
|
|
this.text = pre + add + post;
|
|
let l = end - begin - add.length;
|
|
this.currStart = this.currStart - preCount * l;
|
|
this.currEnd = this.currEnd - (preCount + 1) * l;
|
|
}
|
|
get range() {
|
|
return vscode_languageserver_types_1.Range.create(this.line, this.start, this.line, this.end);
|
|
}
|
|
get currRange() {
|
|
return vscode_languageserver_types_1.Range.create(this.line, this.currStart, this.line, this.currEnd);
|
|
}
|
|
applyEdit(edit) {
|
|
let { range, newText } = edit;
|
|
let start = range.start.character;
|
|
let end = range.end.character;
|
|
let isAdd = start == end;
|
|
if (isAdd) {
|
|
this.add(start - this.currStart, newText);
|
|
}
|
|
else {
|
|
this.replace(start - this.currStart, end - this.currStart, newText);
|
|
}
|
|
}
|
|
get textEdit() {
|
|
return {
|
|
range: this.range,
|
|
newText: this.text
|
|
};
|
|
}
|
|
}
|
|
exports.default = TextRange;
|
|
//# sourceMappingURL=range.js.map
|
|
|
|
/***/ }),
|
|
/* 409 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = __webpack_require__(3);
|
|
const path_1 = tslib_1.__importDefault(__webpack_require__(57));
|
|
const fs_1 = tslib_1.__importDefault(__webpack_require__(55));
|
|
const glob_1 = tslib_1.__importDefault(__webpack_require__(240));
|
|
const os_1 = __webpack_require__(56);
|
|
const util_1 = tslib_1.__importDefault(__webpack_require__(40));
|
|
const fs_2 = __webpack_require__(200);
|
|
async function default_1() {
|
|
if (global.hasOwnProperty('__TEST__'))
|
|
return;
|
|
try {
|
|
let dir = os_1.tmpdir();
|
|
let files = glob_1.default.sync(path_1.default.join(dir, '/coc-*.sock'));
|
|
for (let file of files) {
|
|
let valid = await fs_2.validSocket(file);
|
|
if (!valid)
|
|
await util_1.default.promisify(fs_1.default.unlink)(file);
|
|
}
|
|
files = glob_1.default.sync(path_1.default.join(dir, '/coc-nvim-tscancellation-*'));
|
|
for (let file of files) {
|
|
await util_1.default.promisify(fs_1.default.unlink)(file);
|
|
}
|
|
files = glob_1.default.sync(path_1.default.join(dir, '/ti-*.log'));
|
|
for (let file of files) {
|
|
await util_1.default.promisify(fs_1.default.unlink)(file);
|
|
}
|
|
files = glob_1.default.sync(path_1.default.join(dir, '/coc-*.vim'));
|
|
for (let file of files) {
|
|
if (path_1.default.basename(file) != `coc-${process.pid}.vim`) {
|
|
await util_1.default.promisify(fs_1.default.unlink)(file);
|
|
}
|
|
}
|
|
dir = process.env.XDG_RUNTIME_DIR || dir;
|
|
files = glob_1.default.sync(path_1.default.join(dir, '/coc-nvim-*.log'));
|
|
for (let file of files) {
|
|
if (path_1.default.basename(file) != `coc-nvim-${process.pid}.log`) {
|
|
await util_1.default.promisify(fs_1.default.unlink)(file);
|
|
}
|
|
}
|
|
}
|
|
catch (e) {
|
|
// noop
|
|
}
|
|
}
|
|
exports.default = default_1;
|
|
//# sourceMappingURL=clean.js.map
|
|
|
|
/***/ }),
|
|
/* 410 */
|
|
/***/ (function(module) {
|
|
|
|
module.exports = JSON.parse("{\"name\":\"coc.nvim\",\"version\":\"0.0.74\",\"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/.bin/jest --runInBand --detectOpenHandles --forceExit\",\"test-build\":\"node --trace-warnings node_modules/.bin/jest --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 <chemzqm@gmail.com>\",\"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.7.4\",\"@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.0.2\",\"tslint\":\"^5.19.0\",\"typescript\":\"3.6.2\",\"vscode-languageserver\":\"5.3.0-next.8\"},\"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.10.0\",\"tunnel\":\"^0.0.6\",\"uuid\":\"^3.3.3\",\"vscode-languageserver-protocol\":\"3.15.0-next.6\",\"vscode-languageserver-types\":\"3.15.0-next.2\",\"vscode-uri\":\"^2.0.3\",\"which\":\"^1.3.1\"}}");
|
|
|
|
/***/ })
|
|
/******/ ]); |