UNPKG

coc.nvim

Version:

LSP based intellisense engine for neovim & vim8.

260 lines 8.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol"); const jsonc_parser_1 = require("jsonc-parser"); const is_1 = require("../util/is"); const object_1 = require("../util/object"); const fs_1 = tslib_1.__importDefault(require("fs")); const vscode_uri_1 = require("vscode-uri"); const path_1 = tslib_1.__importDefault(require("path")); const logger = require('../util/logger')('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